rrthomas / recode

Charset converter tool and library
GNU General Public License v3.0
130 stars 12 forks source link

gcc-12.2.0 build warning #50

Open jcumming opened 1 year ago

jcumming commented 1 year ago

In packaging recode 3.7.14 for nixpkgs/unstable, -Werror with gcc-12.2.0 throws this

ecode> request.c: In function 'scan_charset':                            
recode> request.c:989:24: warning: dereference of NULL 'options_pointer' [8;;https://cwe.mitre.org/data/definitions/476.htmlCWE-4768;;] [8;;https://g
cc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-null-dereference-Wanalyzer-null-dereference8;;]
recode>   989 |       *options_pointer = charset_options; 
recode>       |       ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~                                                                                             
recode>   'recode_scan_request': events 1-2                                                                                                          
recode>     |                     
recode>     | 1146 | recode_scan_request (RECODE_REQUEST request, const char *string)                                                                
recode>     |      | ^~~~~~~~~~~~~~~~~~~                                  
recode>     |      | |                                                    
recode>     |      | (1) entry to 'recode_scan_request'
recode>     |......                                                       
recode>     | 1149 |     decode_request (request, string)                 
recode>     |      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                 
recode>     |      |     |                                                
recode>     |      |     (2) calling 'decode_request' from 'recode_scan_request'                                                                     
recode>     |                                                                                                                                        
recode>     +--> 'decode_request': events 3-8                                                                                                        
recode>            |                                                      
recode>            | 1050 | decode_request (RECODE_REQUEST request, const char *string)                          
recode>            |      | ^~~~~~~~~~~~~~                                
recode>            |      | |                                             
recode>            |      | (3) entry to 'decode_request'     
recode>            |......                                                
recode>            | 1055 |   if (!ALLOC (request->scanned_string, strlen (string) + 1, char))       
recode>            |      |      ~
recode>            |      |      |                                                                                                                   recode>            |      |      (4) following 'false' branch...
recode>            | 1056 |     return false;               
recode>            | 1057 |   request->sequence_length = 0;            
recode>            |      |   ~~~~~~~                                     
recode>            |      |   |
recode>            |      |   (5) ...to here                    
recode>            | 1058 |
recode>            | 1059 |   if (*request->scan_cursor)                  
recode>            |      |      ~                                        
recode>            |      |      |   
recode>            |      |      (6) following 'true' branch...
recode>            | 1060 |     {                                                                                                                    
recode>            | 1061 |       if (!scan_request (request))                                                                                       
recode>            |      |       ~~   ~~~~~~~~~~~~~~~~~~~~~~                                                                                        
recode>            |      |       |    |                                                                                                             
recode>            |      |       |    (8) calling 'scan_request' from 'decode_request'                     
recode>            |      |       (7) ...to here       
recode>            |                                                      
recode>            +--> 'scan_request': events 9-10   
recode>                   |                                               
recode>                   | 1011 | scan_request (RECODE_REQUEST request)
recode>                   |      | ^~~~~~~~~~~~                                                                                                      recode>                   |      | |                                                                                                                 recode>                   |      | (9) entry to 'scan_request'
recode>                   |......                                                                                                                    recode>                   | 1015 |   RECODE_SYMBOL charset = scan_charset (request, NULL, NULL, &options);                                           recode>                   |      |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                            recode>                   |      |                           |            
recode>                   |      |                           (10) calling 'scan_charset' from 'scan_request'
recode>                   |                                               
recode>                   +--> 'scan_charset': events 11-16     
recode>                          |                                        
recode>                          |  902 | scan_charset (RECODE_REQUEST request,                                                                      recode>                          |      | ^~~~~~~~~~~~     
recode>                          |      | |                                                                                                          recode>                          |      | (11) entry to 'scan_charset'
recode>                          |......                                                                                                             recode>                          |  916 |   if (!alias)   
recode>                          |      |      ~                    
recode>                          |      |      |   
recode>                          |      |      (12) following 'false' branch (when 'alias' is non-NULL)...                                           
recode>                          |  917 |     return NULL; 
recode>                          |  918 |   charset = alias->symbol;
recode>                          |      |   ~~~~~~~    
recode>                          |      |   |   
recode>                          |      |   (13) ...to here
recode>                          |  919 |                                                                                                            
recode>                          |  920 |   if (before)
recode>                          |      |      ~                                                                                                     
recode>                          |      |      |                                                                                                     
recode>                          |      |      (14) following 'false' branch (when 'before' is NULL)...                                              
recode>                          |......                                                                                                             
recode>                          |  989 |       *options_pointer = charset_options;                                                                  
recode>                          |      |       ~                         
recode>                          |      |       |                                                                                                    
recode>                          |      |       (15) ...to here                                                                                      
recode>                          |......                                                                                                             
recode>                          |  993 |           if (!scan_unsurfacers (request))                                                                 
recode>                          |      |                ~~~~~~~~~~~~~~~~~~~~~~~~~~                                 
recode>                          |      |                |                                                                                           
recode>                          |      |                (16) calling 'scan_unsurfacers' from 'scan_charset'                                         
recode>                          |                                                                                                                   recode>                          +--> 'scan_unsurfacers': events 17-18                                                                               recode>                                 |                                                                                                            recode>                                 |  832 | scan_unsurfacers (RECODE_REQUEST request)                              
recode>                                 |      | ^~~~~~~~~~~~~~~~                                                                                    
recode>                                 |      | |                                                                                                   
recode>                                 |      | (17) entry to 'scan_unsurfacers'                      
recode>                                 |......                                                                                                      
recode>                                 |  861 |   if (surface && surface->unsurfacer)                                                               
recode>                                 |      |      ~                                                                                              
recode>                                 |      |      |                   
recode>                                 |      |      (18) following 'false' branch (when 'surface' is NULL)...                                      
recode>                                 |                                 
recode>                               'scan_unsurfacers': event 19
recode>                                 |     
recode>                                 |cc1:               
recode>                                 | (19): ...to here                
recode>                                 |                       
recode>                          <------+     
recode>                          |                                        
recode>                        'scan_charset': events 20-21
recode>                          |                                        
recode>                          |  993 |           if (!scan_unsurfacers (request))
recode>                          |      |              ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~
recode>                          |      |              | |
recode>                          |      |              | (20) returning to 'scan_charset' from 'scan_unsurfacers'
recode>                          |      |              (21) following 'true' branch...
recode>                          |
recode>                        'scan_charset': event 22                                                                                              
recode>                          |
recode>                          |cc1:                        
recode>                          | (22): ...to here
recode>                          |                                        
recode>                   <------+
recode>                   |                                               
recode>                 'scan_request': events 23-26
recode>                   |                                               
recode>                   | 1015 |   RECODE_SYMBOL charset = scan_charset (request, NULL, NULL, &options);
recode>                   |      |                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
recode>                   |      |                           |
recode>                   |      |                           (23) returning to 'scan_request' from 'scan_charset'
recode>                   | 1016 |                                        
recode>                   | 1017 |   if (!charset)
recode>                   |      |      ~                     
recode>                   |      |      |       
recode>                   |      |      (24) following 'false' branch (when 'charset' is non-NULL)...
recode>                   |......
recode>                   | 1020 |   if (request->scan_cursor[0] == '.' && request->scan_cursor[1] == '.')
recode>                   |      |   ~~ ~       
recode>                   |      |   |  |                   
recode>                   |      |   |  (26) following 'true' branch...
recode>                   |      |   (25) ...to here            
recode>                   |
recode>                 'scan_request': event 27                
recode>                   |
recode>                   |cc1:                                           
recode>                   | (27): ...to here      
recode>                   |          
recode>                 'scan_request': events 28-30
recode>                   |                                                                                                                          
recode>                   | 1021 |     while (request->scan_cursor[0] == '.' && request->scan_cursor[1] == '.')
recode>                   |      |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
recode>                   |      |                                           |
recode>                   |      |                                           (28) following 'true' branch...
recode>                   | 1022 |       {             
recode>                   | 1023 |         request->scan_cursor += 2;
recode>                   |      |         ~~~~~~~    
recode>                   |      |         |                   
recode>                   |      |         (29) ...to here
recode>                   | 1024 |         charset = scan_charset (request, charset, options, NULL);
recode>                   |      |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        
recode>                   |      |                   |
recode>                   |      |                   (30) calling 'scan_charset' from 'scan_request'        
recode>                   |                                               
recode>                   +--> 'scan_charset': events 31-36                                                                                          
recode>                          |                                        
recode>                          |  902 | scan_charset (RECODE_REQUEST request,
recode>                          |      | ^~~~~~~~~~~~  
recode>                          |      | |                     
recode>                          |      | (31) entry to 'scan_charset'
recode>                          |......                        
recode>                          |  916 |   if (!alias)    
recode>                          |      |      ~                                                                                                     
recode>                          |      |      |
recode>                          |      |      (32) following 'false' branch (when 'alias' is non-NULL)...
recode>                          |  917 |     return NULL;
recode>                          |  918 |   charset = alias->symbol;
recode>                          |      |   ~~~~~~~
recode>                          |      |   |
recode>                          |      |   (33) ...to here
recode>                          |  919 |
recode>                          |  920 |   if (before)
recode>                          |      |      ~
recode>                          |      |      |
recode>                          |      |      (34) following 'false' branch (when 'before' is NULL)...
recode>                          |......
recode>                          |  989 |       *options_pointer = charset_options;
recode>                          |      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
recode>                          |      |       |                |
recode>                          |      |       |                (36) dereference of NULL 'options_pointer'
recode>                          |      |       (35) ...to here
recode>                          |

If you have nix installed, this should be reproducable with:

git clone https://github.com/jcumming/nixpkgs.git
cd nixpkgs ; git checkout recode-3-7-14
nix build .#recode
rrthomas commented 1 year ago

Thanks for the report! This looks bogus to me. Event (24) says charset is non-NULL; event (30) calls scan_charset with argument charset as parameter before (so before is non-NULL), so event (34) (before is NULL) cannot happen in this case.

Looking at the code in scan_request, the before argument is always non-NULL when options_pointer is NULL, and vice versa.