Detect SSL error code mishandling.
[openssl.git] / util / mkerr.pl
index 1b2915c7677948b0c48ae7658505f1110b7af467..a5ba05a7966d7593eb519b626a973960b0cd8b19 100644 (file)
@@ -9,6 +9,9 @@ my $reindex = 0;
 my $dowrite = 0;
 my $staticloader = "";
 
+my $pack_errcode;
+my $load_errcode;
+
 while (@ARGV) {
        my $arg = $ARGV[0];
        if($arg eq "-conf") {
@@ -100,15 +103,24 @@ while (($hdr, $lib) = each %libinc)
                    next;
                }
 
-               $cpp = 1 if /^#.*ifdef.*cplusplus/;  # skip "C" declaration
+               if(/\/\*/) {
+                   if (not /\*\//) {           # multiline comment...
+                       $line = $_;             # ... just accumulate
+                       next; 
+                   } else {
+                       s/\/\*.*?\*\///gs;      # wipe it
+                   }
+               }
+
                if ($cpp) {
-                   $cpp = 0 if /^#.*endif/;
+                   $cpp++ if /^#\s*if/;
+                   $cpp-- if /^#\s*endif/;
                    next;
                }
+               $cpp = 1 if /^#.*ifdef.*cplusplus/;  # skip "C" declaration
 
                next if (/^\#/);                      # skip preprocessor directives
 
-               s/\/\*.*?\*\///gs;                   # ignore comments
                s/{[^{}]*}//gs;                      # ignore {} blocks
 
                if (/\{|\/\*/) { # Add a } so editor works...
@@ -125,27 +137,28 @@ while (($hdr, $lib) = each %libinc)
            $defnr++;
            print STDERR "def: $defnr\r" if $debug;
 
+           # The goal is to collect function names from function declarations.
+
            s/^[\n\s]*//g;
            s/[\n\s]*$//g;
-           next if(/typedef\W/);
-           if (/\(\*(\w*)\([^\)]+/) {
-               my $name = $1;
-               $name =~ tr/[a-z]/[A-Z]/;
-               $ftrans{$name} = $1;
-           } elsif (/\w+\W+(\w+)\W*\(\s*\)(\s*__attribute__\(.*\)\s*)?$/s){
-               # K&R C
-               next ;
-           } elsif (/\w+\W+\w+\W*\(.*\)(\s*__attribute__\(.*\)\s*)?$/s) {
-               while (not /\(\)(\s*__attribute__\(.*\)\s*)?$/s) {
-                   s/[^\(\)]*\)(\s*__attribute__\(.*\)\s*)?$/\)/s;
-                   s/\([^\(\)]*\)\)(\s*__attribute__\(.*\)\s*)?$/\)/s;
-               }
-               s/\(void\)//;
-               /(\w+(\{[0-9]+\})?)\W*\(\)/s;
-               my $name = $1;
+
+           # Skip over recognized non-function declarations
+           next if(/typedef\W/ or /DECLARE_STACK_OF/ or /TYPEDEF_.*_OF/);
+
+           # Reduce argument lists to empty ()
+           # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {}
+           while(/\(.*\)/s) {
+               s/\([^\(\)]+\)/\{\}/gs;
+               s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs;    #(*f{}) -> f
+           }
+           # pretend as we didn't use curly braces: {} -> ()
+           s/\{\}/\(\)/gs;
+
+           if (/(\w+)\s*\(\).*/s) {    # first token prior [first] () is
+               my $name = $1;          # a function name!
                $name =~ tr/[a-z]/[A-Z]/;
                $ftrans{$name} = $1;
-           } elsif (/\(/ and not (/=/ or /DECLARE_STACK/)) {
+           } elsif (/[\(\)]/ and not (/=/)) {
                print STDERR "Header $hdr: cannot parse: $_;\n";
            }
        }
@@ -182,6 +195,23 @@ while (($hdr, $lib) = each %libinc)
                }
            }
        }
+
+       if ($debug) {
+               if (defined($rmax{$lib})) {
+                       print STDERR "Max reason code rmax" . "{" . "$lib" . "} = $rmax{$lib}\n";
+               }
+               if (defined($fmax{$lib})) {
+                       print STDERR "Max function code fmax" . "{" . "$lib" . "} = $fmax{$lib}\n";
+               }
+       }
+
+       if ($lib eq "SSL") {
+               if ($rmax{$lib} >= 1000) {
+                       print STDERR "!! ERROR: SSL error codes 1000+ are reserved for alerts.\n";
+                       print STDERR "!!        Any new alerts must be added to $config.\n";
+                       print STDERR "\n";
+               }
+       }
        close IN;
 }
 
@@ -197,11 +227,10 @@ while (($hdr, $lib) = each %libinc)
 # so all those unreferenced can be printed out.
 
 
-print STDERR "Files loaded: " if $debug;
 foreach $file (@source) {
        # Don't parse the error source file.
        next if exists $cskip{$file};
-       print STDERR $file if $debug;
+       print STDERR "File loaded: ".$file."\r" if $debug;
        open(IN, "<$file") || die "Can't open source file $file\n";
        while(<IN>) {
                if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) {
@@ -225,7 +254,7 @@ foreach $file (@source) {
        }
        close IN;
 }
-print STDERR "\n" if $debug;
+print STDERR "                                  \n" if $debug;
 
 # Now process each library in turn.
 
@@ -262,7 +291,7 @@ foreach $lib (keys %csrc)
        } else {
            push @out,
 "/* ====================================================================\n",
-" * Copyright (c) 2001-2003 The OpenSSL Project.  All rights reserved.\n",
+" * Copyright (c) 2001-2005 The OpenSSL Project.  All rights reserved.\n",
 " *\n",
 " * Redistribution and use in source and binary forms, with or without\n",
 " * modification, are permitted provided that the following conditions\n",
@@ -398,13 +427,27 @@ EOF
                $hincf = "\"$hfile\"";
        }
 
+       # If static we know the error code at compile time so use it
+       # in error definitions.
+
+       if ($static)
+               {
+               $pack_errcode = "ERR_LIB_${lib}";
+               $load_errcode = "0";
+               }
+       else
+               {
+               $pack_errcode = "0";
+               $load_errcode = "ERR_LIB_${lib}";
+               }
+
 
        open (OUT,">$cfile") || die "Can't open $cfile for writing";
 
        print OUT <<"EOF";
 /* $cfile */
 /* ====================================================================
- * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -468,6 +511,10 @@ EOF
 
 /* BEGIN ERROR CODES */
 #ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK($pack_errcode,func,0)
+#define ERR_REASON(reason) ERR_PACK($pack_errcode,0,reason)
+
 static ERR_STRING_DATA ${lib}_str_functs[]=
        {
 EOF
@@ -479,7 +526,8 @@ EOF
                if(exists $ftrans{$fn}) {
                        $fn = $ftrans{$fn};
                }
-               print OUT "{ERR_PACK(0,$i,0),\t\"$fn\"},\n";
+#              print OUT "{ERR_PACK($pack_errcode,$i,0),\t\"$fn\"},\n";
+               print OUT "{ERR_FUNC($i),\t\"$fn\"},\n";
        }
        print OUT <<"EOF";
 {0,NULL}
@@ -491,6 +539,7 @@ EOF
        # Add each reason code.
        foreach $i (@reasons) {
                my $rn;
+               my $rstr = "ERR_REASON($i)";
                my $nspc = 0;
                if (exists $err_reason_strings{$i}) {
                        $rn = $err_reason_strings{$i};
@@ -499,9 +548,9 @@ EOF
                        $rn = $1;
                        $rn =~ tr/_[A-Z]/ [a-z]/;
                }
-               $nspc = 40 - length($i) unless length($i) > 40;
+               $nspc = 40 - length($rstr) unless length($rstr) > 40;
                $nspc = " " x $nspc;
-               print OUT "{${i}${nspc},\"$rn\"},\n";
+               print OUT "{${rstr}${nspc},\"$rn\"},\n";
        }
 if($static) {
        print OUT <<"EOF";
@@ -518,8 +567,8 @@ ${staticloader}void ERR_load_${lib}_strings(void)
                {
                init=0;
 #ifndef OPENSSL_NO_ERR
-               ERR_load_strings(ERR_LIB_${lib},${lib}_str_functs);
-               ERR_load_strings(ERR_LIB_${lib},${lib}_str_reasons);
+               ERR_load_strings($load_errcode,${lib}_str_functs);
+               ERR_load_strings($load_errcode,${lib}_str_reasons);
 #endif
 
                }