File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/PreventSQLInjection.pm
Criterion Covered Total %
statement 158 162 97.5
branch 88 104 84.6
condition 43 59 72.8
subroutine 25 26 96.1
pod 14 14 100.0
total 328 365 89.8


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ValuesAndExpressions::PreventSQLInjection;
2              
3 3     3   303630 use 5.006001;
  3         12  
4 3     3   18 use strict;
  3         5  
  3         97  
5 3     3   14 use warnings;
  3         8  
  3         110  
6              
7 3     3   15 use base 'Perl::Critic::Policy';
  3         4  
  3         2021  
8              
9 3     3   399013 use Carp;
  3         10  
  3         207  
10 3     3   2566 use Data::Dumper;
  3         19314  
  3         204  
11 3     3   20 use Perl::Critic::Utils;
  3         5  
  3         60  
12 3     3   1666 use Readonly;
  3         4  
  3         111  
13 3     3   1271 use String::InterpolatedVariables;
  3         866  
  3         79  
14 3     3   1384 use Try::Tiny;
  3         4881  
  3         5116  
15              
16              
17             =head1 NAME
18              
19             Perl::Critic::Policy::ValuesAndExpressions::PreventSQLInjection - Prevent SQL injection in interpolated strings.
20              
21              
22             =head1 VERSION
23              
24             Version 1.4.0
25              
26             =cut
27              
28             our $VERSION = '1.4.0';
29              
30              
31             =head1 AFFILIATION
32              
33             This is a standalone policy not part of a larger PerlCritic Policies group.
34              
35              
36             =head1 DESCRIPTION
37              
38             When building SQL statements manually instead of using an ORM, any input must
39             be quoted or passed using placeholders to prevent the introduction of SQL
40             injection vectors. This policy attempts to detect the most common sources of
41             SQL injection in manually crafted SQL statements, by detecting the use of
42             variables inside interpolated strings that look like SQL statements.
43              
44             In other words, this policy searches for code such as:
45              
46             my $sql = "SELECT * FROM $table WHERE field = $value";
47              
48             But would leave alone:
49              
50             my $string = "Hello $world";
51              
52              
53             =head1 CONFIGURATION
54              
55             =head2 quoting_methods
56              
57             A space-separated list of methods that are known to always return a safely
58             quoted result.
59              
60             For example, to declare C<custom_quote()> as safe, add the following to your
61             C<.perlcriticrc>:
62              
63             [ValuesAndExpressions::PreventSQLInjection]
64             quoting_methods = 'custom_quote'
65              
66             By default, C<quote()> and C<quote_identifier> are considered safe, given their
67             ubiquity in code that uses DBI. Note however that specifying manually a new
68             list for C<quoting_methods> will override those defaults, so you will have to
69             do this if you want to keep the two default methods but add your custom one to
70             the list:
71              
72             [ValuesAndExpressions::PreventSQLInjection]
73             quoting_methods = 'quote quote_identifier custom_quote'
74              
75              
76             =head2 safe_functions
77              
78             A space-separated string listing the functions that always return a safely
79             quoted value.
80              
81             For example, to declare C<quote_function()> and
82             C<My::Package::quote_external_function()> as safe, add the following to your
83             C<.perlcriticrc>:
84              
85             [ValuesAndExpressions::PreventSQLInjection]
86             safe_functions = 'quote_function My::Package::quote_external_function'
87              
88             By default, no functions are considered safe.
89              
90              
91             =head1 MARKING ELEMENTS AS SAFE
92              
93             You can disable this policy on a particular string with the usual PerlCritic
94             syntax:
95              
96             my $sql = "SELECT * FROM table WHERE field = $value"; ## no critic (PreventSQLInjection)
97              
98             This is however not recommended, even if you know that $value is safe because
99             it was previously quoted with something such as:
100              
101             my $value = $dbh->quote( $user_value );
102              
103             The risk there is that someone will later modify your code and introduce unsafe
104             variables by accident, which will then not get reported. To prevent this, this
105             module has a special C<## SQL safe (...)> syntax described below.
106              
107             =head2 Marking variables as safe
108              
109             To indicate that a variable has been manually checked and determined to be
110             safe, add a comment on the same line using this syntax: C<## SQL safe ($var1,
111             $var2, ...)>.
112              
113             For example:
114              
115             my $sql = "SELECT * FROM table WHERE field = $value"; ## SQL safe($value)
116              
117             That said, you should always convert your code to use placeholders instead
118             where possible.
119              
120             =head2 Marking functions / class methods as safe
121              
122             To indicate that a function or class method has been manually checked and
123             determined that it will always return a safe output, add comment on the same
124             line using the C<## SQL safe(function_name>) syntax:
125              
126             my $sql = "SELECT * FROM table WHERE field = "
127             . some_safe_method( $value ); ## SQL safe (&some_safe_method)
128              
129             my $sql = "SELECT * FROM table WHERE field = "
130             . Package::Name::some_safe_method( $value ); ## SQL safe (&Package::Name::some_safe_method)
131              
132             Note that class methods (a function called with C<-E<gt>> on a package name)
133             still need to be declared with C<::> in the list of safe elements:
134              
135             my $sql = "SELECT * FROM table WHERE field = "
136             . Package::Name->some_safe_method( $value ); ## SQL safe (&Package::Name::some_safe_method)
137              
138             =head2 SQL safe syntax notes
139              
140             =over 4
141              
142             =item *
143              
144             This policy supports both comma-separated and space-separated lists to
145             describe safe variables. In other words, C<## SQL safe ($var1, $var2, ...)> and
146             C<## SQL safe ($var1 $var2 ...)> are strictly equivalent.
147              
148             =item *
149              
150             You can mix function names and variables in the comments to describe safe elements:
151              
152             C<## SQL safe ($var1, &function_name, $var2, ...)>
153              
154             =back
155              
156              
157             =head1 LIMITATIONS
158              
159             There are B<many> sources of SQL injection flaws, and this module comes with no guarantee whatsoever. It focuses on the most obvious flaws, but you should still learn more about SQL injection techniques to manually detect more advanced issues.
160              
161             Possible future improvements for this module:
162              
163             =over 4
164              
165             =item * Detect use of sprintf()
166              
167             This should probably be considered a violation:
168              
169             my $sql = sprintf(
170             'SELECT * FROM %s',
171             $table
172             );
173              
174             =item * Detect use of constants
175              
176             This should not be considered a violation, since constants cannot be modified
177             by user input:
178              
179             use Const::Fast;
180             const my $FOOBAR => 12;
181              
182             $dbh->do("SELECT name FROM categories WHERE id = $FOOBAR");
183              
184             =item * Detect SQL string modifications.
185              
186             Currently, this module only analyzes strings when they are declared, and does not account for later modifications.
187              
188             This should be reviewed as part of this module:
189              
190             my $sql = "select from ";
191             $sql .= $table;
192              
193             As well as this:
194              
195             my $sql = "select from ";
196             $sql = "$sql $table";
197              
198             =item
199              
200             =back
201              
202             =cut
203              
204             Readonly::Scalar my $DESCRIPTION => 'SQL injection risk.';
205             Readonly::Scalar my $EXPLANATION => 'Variables in interpolated SQL string are susceptible to SQL injection: %s';
206              
207             # Default for the name of the methods that make a variable safe to use in SQL
208             # strings.
209             Readonly::Scalar my $QUOTING_METHODS_DEFAULT => q|
210             quote_identifier
211             quote
212             |;
213              
214             # Default for the name of the packages and functions / class methods that are safe to
215             # concatenate to SQL strings.
216             Readonly::Scalar my $SAFE_FUNCTIONS_DEFAULT => q|
217             |;
218              
219             # Regex to detect comments like ## SQL safe ($var1, $var2).
220             Readonly::Scalar my $SQL_SAFE_COMMENTS_REGEX => qr/
221             \A
222             (?: [#]! .*? )?
223             \s*
224             # Find the ## annotation starter.
225             [#][#]
226             \s*
227             # "SQL safe" is our keyword.
228             SQL \s+ safe
229             \s*
230             # List of safe variables between parentheses.
231             \(\s*(.*?)\s*\)
232             /ixms;
233              
234              
235             =head1 FUNCTIONS
236              
237             =head2 supported_parameters()
238              
239             Return an array with information about the parameters supported.
240              
241             my @supported_parameters = $policy->supported_parameters();
242              
243             =cut
244              
245             sub supported_parameters
246             {
247             return (
248             {
249 54     54 1 191990 name => 'quoting_methods',
250             description => 'A space-separated string listing the methods that return a safely quoted value.',
251             default_string => $QUOTING_METHODS_DEFAULT,
252             behavior => 'string',
253             },
254             {
255             name => 'safe_functions',
256             description => 'A space-separated string listing the functions that return a safely quoted value',
257             default_string => $SAFE_FUNCTIONS_DEFAULT,
258             behavior => 'string',
259             },
260             );
261             }
262              
263              
264             =head2 default_severity()
265              
266             Return the default severify for this policy.
267              
268             my $default_severity = $policy->default_severity();
269              
270             =cut
271              
272             sub default_severity
273             {
274 27     27 1 337 return $Perl::Critic::Utils::SEVERITY_HIGHEST;
275             }
276              
277              
278             =head2 default_themes()
279              
280             Return the default themes this policy is included in.
281              
282             my $default_themes = $policy->default_themes();
283              
284             =cut
285              
286             sub default_themes
287             {
288 1     1 1 699 return qw( security );
289             }
290              
291              
292             =head2 applies_to()
293              
294             Return the class of elements this policy applies to.
295              
296             my $class = $policy->applies_to();
297              
298             =cut
299              
300             sub applies_to
301             {
302 54     54 1 327762 return qw(
303             PPI::Token::Quote
304             PPI::Token::HereDoc
305             );
306             }
307              
308              
309             =head2 violates()
310              
311             Check an element for violations against this policy.
312              
313             my $policy->violates(
314             $element,
315             $document,
316             );
317              
318             =cut
319              
320             sub violates
321             {
322 85     85 1 5442 my ( $self, $element, $doc ) = @_;
323              
324 85         254 parse_config_parameters( $self );
325              
326 85         244 parse_comments( $self, $doc );
327              
328             # Make sure the first string looks like a SQL statement before investigating
329             # further.
330             return ()
331 85 100       238 if !is_sql_statement( $element );
332              
333             # Find SQL injection vulnerabilities.
334 53         163 my $sql_injections = detect_sql_injections( $self, $element );
335              
336             # Return violations if any.
337 53 100 66     626 return defined( $sql_injections ) && scalar( @$sql_injections ) != 0
338             ? $self->violation(
339             $DESCRIPTION,
340             sprintf(
341             $EXPLANATION,
342             join( ', ', @$sql_injections ),
343             ),
344             $element,
345             )
346             : ();
347             }
348              
349              
350             =head1 INTERNAL FUNCTIONS
351              
352             =head2 detect_sql_injections()
353              
354             Detect SQL injections vulnerabilities tied to the PPI element specified.
355              
356             my $sql_injections = detect_sql_injections( $policy, $element );
357              
358             =cut
359              
360             sub detect_sql_injections
361             {
362 53     53 1 116 my ( $self, $element ) = @_;
363              
364 53         96 my $sql_injections = [];
365 53         81 my $token = $element;
366 53   66     349 while ( defined( $token ) && $token ne '' )
367             {
368             # If the token is a string, we need to analyze it for interpolated
369             # variables.
370 282 100 100     13023 if ( $token->isa( 'PPI::Token::HereDoc' ) || $token->isa( 'PPI::Token::Quote' ) ) ## no critic (ControlStructures::ProhibitCascadingIfElse)
    100 100        
    100 66        
    100 100        
    100 100        
    100          
    100          
371             {
372 77 50       138 push( @$sql_injections, @{ analyze_string_injections( $self, $token ) || [] } );
  77         196  
373             }
374             # If it is a concatenation operator, continue to the next token.
375             elsif ( $token->isa('PPI::Token::Operator') && $token->content() eq '.' )
376             {
377             # Skip to the next token.
378             }
379             # If it is a semicolon, we're at the end of the statement and we can finish
380             # the process.
381             elsif ( $token->isa('PPI::Token::Structure') && $token->content() eq ';' )
382             {
383 44         284 last;
384             }
385             # If we detect a ':' operator, we're at the end of the second argument in a
386             # ternary "... ? ... : ..." and we need to finish the process here as the
387             # third argument is not concatenated to the this string and will be
388             # analyzed separately.
389             elsif ( $token->isa('PPI::Token::Operator') && $token->content() eq ':' )
390             {
391 3         61 last;
392             }
393             # If it is a list-separating comma, this list element ends here and we can
394             # finish the process.
395             elsif ( $token->isa('PPI::Token::Operator') && $token->content() eq ',' )
396             {
397 1         30 last;
398             }
399             # If it is a symbol, it is concatenated to a SQL statement which is an
400             # injection risk.
401             elsif ( $token->isa('PPI::Token::Symbol') )
402             {
403 21         78 my ( $variable, $is_quoted ) = get_complete_variable( $self, $token );
404 21 100       59 if ( !$is_quoted )
405             {
406 15         47 my $safe_elements = get_safe_elements( $self, $token->line_number() );
407             push( @$sql_injections, $variable )
408 15 100       91 if !exists( $safe_elements->{ $variable } );
409             }
410             }
411             # If it is a word, it may be a function/method call on a package, which is
412             # an injection risk.
413             elsif ( $token->isa('PPI::Token::Word') )
414             {
415             # Find out if the PPO::Token::Word is the beginning of a call or not.
416 22         61 my ( $function_name, $is_quoted ) = get_function_name( $self, $token );
417 22 100 100     210 if ( defined( $function_name ) && !$is_quoted )
418             {
419 9         25 my $safe_elements = get_safe_elements( $self, $token->line_number() );
420             push( @$sql_injections, $function_name )
421 9 100       47 if !exists( $safe_elements->{ '&' . $function_name } );
422             }
423             }
424              
425             # Move to examining the next sibling token.
426 234         2191 $token = $token->snext_sibling();
427             }
428              
429 53         309 return $sql_injections;
430             }
431              
432              
433             =head2 get_function_name()
434              
435             Retrieve full name (including the package name) of a class function/method
436             based on a PPI::Token::Word object, and indicate if it is a call that returns
437             quoted data making it safe to include directly into SQL strings.
438              
439             my ( $function_name, $is_quoted ) = get_function_name( $policy, $token );
440              
441             =cut
442              
443             sub get_function_name
444             {
445 22     22 1 30 my ( $self, $token ) = @_;
446              
447 22 50       82 croak 'The first parameter needs to be a PPI::Token::Word object'
448             if !$token->isa('PPI::Token::Word');
449              
450 22         51 my $next_sibling = $token->snext_sibling();
451             return ()
452 22 50 33     414 if !defined( $next_sibling ) || ( $next_sibling eq '' );
453              
454 22         738 my ( $package, $function_name );
455              
456             # Catch Package::Name->method().
457 22 100 66     69 if ( $next_sibling->isa('PPI::Token::Operator') && ( $next_sibling->content() eq '->' ) )
    50          
458             {
459 4         30 my $function = $next_sibling->snext_sibling();
460              
461             return ()
462 4 50 33     66 if !defined( $function ) || ( $function eq '' );
463             return ()
464 4 50       50 if !$function->isa('PPI::Token::Word');
465              
466 4         9 $package = $token->content();
467 4         14 $function_name = $function->content();
468              
469 4         15 $function->{'_handled'} = 1;
470             }
471             # Catch Package::Name::function().
472             elsif ( $next_sibling->isa('PPI::Structure::List') )
473             {
474             # Package::Name->method() will result in two PPI::Token::Word being
475             # detected, one for 'Package::Name' and one for 'method'. 'Package::Name'
476             # will be caught in the if() block above, but 'method' would get caught
477             # separately by this block. To prevent this, we scan the previous sibling
478             # here and skip if we find that it is a '->' operator.
479 18         248 my $previous_sibling = $token->sprevious_sibling();
480             return ()
481 18 100 66     457 if $previous_sibling->isa('PPI::Token::Operator') && ( $previous_sibling->content() eq '->' );
482              
483 6         41 my $content = $token->content();
484              
485             # Catch function calls in the same namespace.
486 6 100       29 if ( $content !~ /::/ )
487             {
488 3         8 ( $package, $function_name ) = ( undef, $content );
489             }
490             # Catch function calls in a different namespace.
491             else
492             {
493 3         20 ( $package, $function_name ) = $content =~ /^(.*)::([^:]+)$/;
494             }
495             }
496             else
497             {
498 0         0 return ();
499             }
500              
501 10         18 my $full_name = join( '::', grep { defined( $_ ) } ( $package, $function_name ) );
  20         45  
502 10 100 66     44 my $is_safe = defined( $self->{'_safe_functions_regex'} ) && ( $full_name =~ $self->{'_safe_functions_regex'} )
503             ? 1
504             : 0;
505 10         24 return ( $full_name, $is_safe );
506             }
507              
508              
509             =head2 get_complete_variable()
510              
511             Retrieve a complete variable starting with a PPI::Token::Symbol object, and
512             indicate if the variable has used a quoting method to make it safe to use
513             directly in SQL strings.
514              
515             my ( $variable, $is_quoted ) = get_complete_variable( $policy, $token );
516              
517             For example, if you have $variable->{test}->[0] in your code, PPI will identify
518             $variable as a PPI::Token::Symbol, and calling this function on that token will
519             return the whole "$variable->{test}->[0]" string.
520              
521             =cut
522              
523             sub get_complete_variable
524             {
525 21     21 1 37 my ( $self, $token ) = @_;
526              
527 21 50       79 croak 'The first parameter needs to be a PPI::Token::Symbol object'
528             if !$token->isa('PPI::Token::Symbol');
529              
530 21         47 my $variable = $token->content();
531 21         89 my $is_quoted = 0;
532 21         22 my $sibling = $token;
533 21         37 while ( 1 )
534             {
535 58         472 $sibling = $sibling->next_sibling();
536 58 50 33     1169 last if !defined( $sibling ) || ( $sibling eq '' );
537              
538 58 100 66     1507 if ( $sibling->isa('PPI::Token::Operator') && $sibling->content() eq '->' )
    100 66        
    100 100        
      100        
539             {
540 20         137 $variable .= '->';
541             }
542             elsif ( $sibling->isa('PPI::Structure::Subscript') )
543             {
544 17         31 $variable .= $sibling->content();
545             }
546             elsif ( $sibling->isa('PPI::Token::Word')
547             && $sibling->method_call()
548             && defined( $self->{'_quoting_methods_regex'} )
549             && ( $sibling->content =~ $self->{'_quoting_methods_regex'} )
550             )
551             {
552 6         278 $is_quoted = 1;
553 6         11 last;
554             }
555             else
556             {
557 15         95 last;
558             }
559             }
560              
561 21         90 return ( $variable, $is_quoted );
562             }
563              
564              
565             =head2 is_sql_statement()
566              
567             Return a boolean indicating whether a string is potentially the beginning of a SQL statement.
568              
569             my $is_sql_statement = is_sql_statement( $token );
570              
571             =cut
572              
573             sub is_sql_statement
574             {
575 85     85 1 211 my ( $token ) = @_;
576 85         237 my $content = get_token_content( $token );
577              
578 85 100       725 return $content =~ /^ \s* (?: SELECT | INSERT | UPDATE | DELETE ) \b/six
579             ? 1
580             : 0;
581             }
582              
583              
584             =head2 get_token_content()
585              
586             Return the text content of a PPI token.
587              
588             my $content = get_token_content( $token );
589              
590             =cut
591              
592             sub get_token_content
593             {
594 141     141 1 168 my ( $token ) = @_;
595              
596             # Retrieve the string's content.
597 141         134 my $content;
598 141 100       739 if ( $token->isa('PPI::Token::HereDoc') )
    50          
599             {
600 12         39 my @heredoc = $token->heredoc();
601 12         152 $content = join( '', @heredoc );
602             }
603             elsif ( $token->isa('PPI::Token::Quote' ) )
604             {
605             # ->string() strips off the leading and trailing quotation signs.
606 129         377 $content = $token->string();
607             }
608             else
609             {
610 0         0 $content = $token->content();
611             }
612              
613 141         1431 return $content;
614             }
615              
616              
617             =head2 analyze_string_injections()
618              
619             Analyze a token representing a string and returns an arrayref of variables that
620             are potential SQL injection vectors.
621              
622             my $sql_injection_vector_names = analyze_string_injections(
623             $policy,
624             $token,
625             );
626              
627             =cut
628              
629             sub analyze_string_injections
630             {
631 77     77 1 150 my ( $policy, $token ) = @_;
632              
633             my $sql_injections =
634             try
635             {
636             # Single quoted strings aren't prone to SQL injection.
637             return
638 77 100   77   4293 if $token->isa('PPI::Token::Quote::Single');
639              
640             # PPI treats HereDoc differently than Quote and QuoteLike for the moment,
641             # this may however change in the future according to the documentation of
642             # PPI.
643 56         173 my $is_heredoc = $token->isa('PPI::Token::HereDoc');
644              
645             # Retrieve the string's content.
646 56         167 my $content = get_token_content( $token );
647              
648             # Find the list of variables marked as safe using "## SQL safe".
649             # Note: comments will appear at the end of the token, so we need to
650             # determine the ending line number instead of the beginning line
651             # number.
652 56         240 my $extra_height_span =()= $content =~ /\n/g;
653 56 100       218 my $safe_elements = get_safe_elements(
654             $policy, #$self
655             $token->line_number()
656             # Heredoc comments will be on the same line as the opening marker.
657             + ( $is_heredoc ? 0 : $extra_height_span ),
658             );
659              
660             # Find all the variables that appear in the string.
661             my $unsafe_variables = [
662 32         1353 grep { !$safe_elements->{ $_ } }
663 56         78 @{ String::InterpolatedVariables::extract( $content ) }
  56         235  
664             ];
665              
666             # Based on the token type, determine if it is interpolated and report any
667             # unsafe variables.
668 56 100       665 if ( $token->isa('PPI::Token::Quote::Double') )
    100          
    50          
669             {
670 49 100       322 return $unsafe_variables
671             if scalar( @$unsafe_variables ) != 0;
672             }
673             elsif ( $token->isa('PPI::Token::Quote::Interpolate') )
674             {
675 1         5 my $raw_content = $token->content();
676 1         13 my ( $lead ) = $raw_content =~ /\A(qq?)([^q])/s;
677 1 50       9 croak "Unknown format for >$raw_content<"
678             if !defined( $lead );
679              
680             # Skip single quoted strings.
681 1 50       3 return if $lead eq 'q';
682              
683 1 50       8 return $unsafe_variables
684             if scalar( @$unsafe_variables ) != 0;
685             }
686             elsif ( $is_heredoc )
687             {
688             # Single quoted heredocs are not interpolated, so they're safe.
689             # Note: '_mode' doesn't seem to be publicly accessible, and the tokenizer
690             # destroys the part of the heredoc termination marker that would
691             # allow determining whether it's interpolated, so the only option
692             # is to rely on the private property of the token here.
693 6 100       29 return if $token->{'_mode'} ne 'interpolate';
694              
695 5 100       33 return $unsafe_variables
696             if scalar( @$unsafe_variables ) != 0;
697             }
698              
699 43         162 return;
700             }
701             catch
702             {
703 0     0   0 print STDERR "Error: $_\n";
704 0         0 return;
705 77         813 };
706              
707 77 100       2312 return defined( $sql_injections )
708             ? $sql_injections
709             : [];
710             }
711              
712              
713             =head2 get_safe_elements()
714              
715             Return a hashref with safe element names as the keys.
716              
717             my $safe_elements = get_safe_elements(
718             $policy,
719             $line_number,
720             );
721              
722             =cut
723              
724             sub get_safe_elements
725             {
726 80     80 1 1403 my ( $self, $line_number ) = @_;
727              
728             # Validate input and state.
729             croak 'Parsed comments not found'
730 80 50       289 if !defined( $self->{'_sqlsafe'} );
731 80 50 33     612 croak 'A line number is mandatory'
732             if !defined( $line_number ) || ( $line_number !~ /\A\d+\Z/ );
733              
734             # If there's nothing in the cache for that line, return immediately.
735             return {}
736 80 100       311 if !exists( $self->{'_sqlsafe'}->{ $line_number } );
737              
738             # Return a hash of safe element names.
739             return {
740             map
741 44         172 { $_ => 1 }
742 30         41 @{ $self->{'_sqlsafe'}->{ $line_number } }
  30         74  
743             };
744             }
745              
746              
747             =head2 parse_comments()
748              
749             Parse the comments for the current document and identify elements marked as
750             SQL safe.
751              
752             parse_comments(
753             $policy,
754             $ppi_document,
755             );
756              
757             =cut
758              
759             sub parse_comments
760             {
761 85     85 1 148 my ( $self, $doc ) = @_;
762              
763             # Only parse if we haven't done so already.
764             return
765 85 100       237 if defined( $self->{'_sqlsafe'} );
766              
767             # Parse all the comments for this document.
768 54         172 $self->{'_sqlsafe'} = {};
769 54   100     270 my $comments = $doc->find('PPI::Token::Comment') || [];
770 54         819 foreach my $comment ( @$comments )
771             {
772             # Determine if the line is a "SQL safe" comment.
773 19         170 my ( $safe_elements ) = $comment =~ $SQL_SAFE_COMMENTS_REGEX;
774 19 50       309 next if !defined( $safe_elements );
775              
776             # Store list of safe elements for that line.
777             push(
778 19         36 @{ $self->{'_sqlsafe'}->{ $comment->line_number() } },
  19         97  
779             split( /[\s,]+(?=[\$\@\%\&])/, $safe_elements )
780             );
781             }
782              
783             #print STDERR "SQL safe elements: ", Dumper( $self->{'_sqlsafe'} ), "\n";
784 54         610 return;
785             }
786              
787              
788             =head2 parse_config_parameters()
789              
790             Parse the parameters from the C<.perlcriticrc> file, if any are specified
791             there.
792              
793             parse_config_parameters( $policy );
794              
795             =cut
796              
797             sub parse_config_parameters
798             {
799 85     85 1 137 my ( $self ) = @_;
800              
801 85 100       320 if ( !exists( $self->{'_quoting_methods_regex'} ) )
802             {
803 54 100       297 if ( $self->{'_quoting_methods'} =~ /\w/ )
804             {
805 53         552 my $regex_components = join( '|', grep { $_ =~ /\w/ } split( /,?\s+/, $self->{'_quoting_methods'} ) );
  155         523  
806 53         480 $self->{'_quoting_methods_regex'} = qr/^(?:$regex_components)$/x;
807             }
808             else
809             {
810 1         3 $self->{'_quoting_methods_regex'} = undef;
811             }
812             }
813              
814 85 100       260 if ( !exists( $self->{'_safe_functions_regex'} ) )
815             {
816 54 100       202 if ( $self->{'_safe_functions'} =~ /\w/ )
817             {
818 1         6 my $regex_components = join( '|', grep { $_ =~ /\w/ } split( /,?\s+/, $self->{'_safe_functions'} ) );
  1         4  
819 1         16 $self->{'_safe_functions_regex'} = qr/^(?:$regex_components)$/x;
820             }
821             else
822             {
823 53         228 $self->{'_safe_functions_regex'} = undef;
824             }
825             }
826              
827 85         150 return;
828             }
829              
830              
831             =head1 BUGS
832              
833             Please report any bugs or feature requests through the web interface at
834             L<https://github.com/guillaumeaubert/Perl-Critic-Policy-ValuesAndExpressions-PreventSQLInjection/issues>.
835             I will be notified, and then you'll automatically be notified of progress on
836             your bug as I make changes.
837              
838              
839             =head1 SUPPORT
840              
841             You can find documentation for this module with the perldoc command.
842              
843             perldoc Perl::Critic::Policy::ValuesAndExpressions::PreventSQLInjection
844              
845              
846             You can also look for information at:
847              
848             =over 4
849              
850             =item * GitHub (report bugs there)
851              
852             L<https://github.com/guillaumeaubert/Perl-Critic-Policy-ValuesAndExpressions-PreventSQLInjection/issues>
853              
854             =item * AnnoCPAN: Annotated CPAN documentation
855              
856             L<http://annocpan.org/dist/Perl-Critic-Policy-ValuesAndExpressions-PreventSQLInjection>
857              
858             =item * CPAN Ratings
859              
860             L<http://cpanratings.perl.org/d/Perl-Critic-Policy-ValuesAndExpressions-PreventSQLInjection>
861              
862             =item * MetaCPAN
863              
864             L<https://metacpan.org/release/Perl-Critic-Policy-ValuesAndExpressions-PreventSQLInjection>
865              
866             =back
867              
868              
869             =head1 AUTHOR
870              
871             L<Guillaume Aubert|https://metacpan.org/author/AUBERTG>,
872             C<< <aubertg at cpan.org> >>.
873              
874              
875             =head1 COPYRIGHT & LICENSE
876              
877             Copyright 2013-2017 Guillaume Aubert.
878              
879             This code is free software; you can redistribute it and/or modify it under the
880             same terms as Perl 5 itself.
881              
882             This program is distributed in the hope that it will be useful, but WITHOUT ANY
883             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
884             PARTICULAR PURPOSE. See the LICENSE file for more details.
885              
886             =cut
887              
888             1;