OpenSSL 1.1.1-pre2

This commit is contained in:
Hakase
2018-04-07 17:29:40 +09:00
parent 82a44d2483
commit bbac8ca55d
17755 changed files with 221242 additions and 98415 deletions
Regular → Executable
+619 -637
View File
@@ -1,590 +1,562 @@
#! /usr/bin/env perl
# Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
my $config = "crypto/err/openssl.ec";
my $debug = 0;
my $unref = 0;
my $rebuild = 0;
my $static = 1;
my $recurse = 0;
my $reindex = 0;
my $dowrite = 0;
my $staticloader = "";
my @t = localtime();
my $YEAR = @t[5] + 1900;
use strict;
use warnings;
my $pack_errcode;
my $load_errcode;
use lib ".";
use configdata;
my $errcount;
my $year = (localtime)[5] + 1900;
my $config = "crypto/err/openssl.ec";
my $debug = 0;
my $internal = 0;
my $nowrite = 0;
my $rebuild = 0;
my $reindex = 0;
my $static = 0;
my $unref = 0;
my %modules = ();
while (@ARGV) {
my $arg = $ARGV[0];
if($arg eq "-conf") {
shift @ARGV;
$config = shift @ARGV;
} elsif($arg eq "-hprefix") {
shift @ARGV;
$hprefix = shift @ARGV;
} elsif($arg eq "-debug") {
$debug = 1;
$unref = 1;
shift @ARGV;
} elsif($arg eq "-rebuild") {
$rebuild = 1;
shift @ARGV;
} elsif($arg eq "-recurse") {
$recurse = 1;
shift @ARGV;
} elsif($arg eq "-reindex") {
$reindex = 1;
shift @ARGV;
} elsif($arg eq "-nostatic") {
$static = 0;
shift @ARGV;
} elsif($arg eq "-staticloader") {
$staticloader = "static ";
shift @ARGV;
} elsif($arg eq "-unref") {
$unref = 1;
shift @ARGV;
} elsif($arg eq "-write") {
$dowrite = 1;
shift @ARGV;
} elsif($arg eq "-help" || $arg eq "-h" || $arg eq "-?" || $arg eq "--help") {
print STDERR <<"EOF";
mkerr.pl [options] ...
my $errors = 0;
my @t = localtime();
my $YEAR = $t[5] + 1900;
sub phase
{
my $text = uc(shift);
print STDERR "\n---\n$text\n" if $debug;
}
sub help
{
print STDERR <<"EOF";
mkerr.pl [options] [files...]
Options:
-conf F Use the config file F instead of the default one:
crypto/err/openssl.ec
-conf FILE Use the named config file FILE instead of the default.
-hprefix P Prepend the filenames in generated #include <header>
statements with prefix P. Default: 'openssl/' (without
the quotes, naturally)
NOTE: not used any more because our include directory
structure has changed.
-debug Verbose output debugging on stderr.
-debug Turn on debugging verbose output on stderr.
-internal Generate code that is to be built as part of OpenSSL itself.
Also scans internal list of files.
-rebuild Rebuild all header and C source files, irrespective of the
fact if any error or function codes have been added/removed.
Default: only update files for libraries which saw change
(of course, this requires '-write' as well, or no
files will be touched!)
-module M Only useful with -internal!
Only write files for library module M. Whether files are
actually written or not depends on other options, such as
-rebuild.
Note: this option is cumulative. If not given at all, all
internal modules will be considered.
-recurse scan a preconfigured set of directories / files for error and
function codes:
(<crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>, <apps/*.c>)
When this option is NOT specified, the filelist is taken from
the commandline instead. Here, wildcards may be embedded. (Be
sure to escape those to prevent the shell from expanding them
for you when you wish mkerr.pl to do so instead.)
Default: take file list to scan from the command line.
-nowrite Do not write the header/source files, even if changed.
-reindex Discard the numeric values previously assigned to the error
and function codes as extracted from the scanned header files;
instead renumber all of them starting from 100. (Note that
the numbers assigned through 'R' records in the config file
remain intact.)
Default: keep previously assigned numbers. (You are warned
when collisions are detected.)
-rebuild Rebuild all header and C source files, even if there
were no changes.
-nostatic Generates a different source code, where these additional
functions are generated for each library specified in the
config file:
void ERR_load_<LIB>_strings(void);
void ERR_unload_<LIB>_strings(void);
void ERR_<LIB>_error(int f, int r, char *fn, int ln);
#define <LIB>err(f,r) ERR_<LIB>_error(f,r,OPENSSL_FILE,OPENSSL_LINE)
while the code facilitates the use of these in an environment
where the error support routines are dynamically loaded at
runtime.
Default: 'static' code generation.
-reindex Ignore previously assigned values (except for R records in
the config file) and renumber everything starting at 100.
-staticloader Prefix generated functions with the 'static' scope modifier.
Default: don't write any scope modifier prefix.
-static Make the load/unload functions static.
-unref Print out unreferenced function and reason codes.
-unref List all unreferenced function and reason codes on stderr;
implies -nowrite.
-write Actually (over)write the generated code to the header and C
source files as assigned to each library through the config
file.
Default: don't write.
-help Show this help text.
-help / -h / -? / --help Show this help text.
... Additional arguments are added to the file list to scan,
assuming '-recurse' was NOT specified on the command line.
... Additional arguments are added to the file list to scan,
if '-internal' was NOT specified on the command line.
EOF
exit 1;
} else {
last;
}
}
if($recurse) {
@source = ( <crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>, <ssl/*/*.c> )
while ( @ARGV ) {
my $arg = $ARGV[0];
last unless $arg =~ /-.*/;
$arg = $1 if $arg =~ /-(-.*)/;
if ( $arg eq "-conf" ) {
$config = $ARGV[1];
shift @ARGV;
} elsif ( $arg eq "-debug" ) {
$debug = 1;
$unref = 1;
} elsif ( $arg eq "-internal" ) {
$internal = 1;
} elsif ( $arg eq "-nowrite" ) {
$nowrite = 1;
} elsif ( $arg eq "-rebuild" ) {
$rebuild = 1;
} elsif ( $arg eq "-reindex" ) {
$reindex = 1;
} elsif ( $arg eq "-static" ) {
$static = 1;
} elsif ( $arg eq "-unref" ) {
$unref = 1;
$nowrite = 1;
} elsif ( $arg eq "-module" ) {
shift @ARGV;
$modules{uc $ARGV[0]} = 1;
} elsif ( $arg =~ /-*h(elp)?/ ) {
&help();
exit;
} elsif ( $arg =~ /-.*/ ) {
die "Unknown option $arg; use -h for help.\n";
}
shift @ARGV;
}
my @source;
if ( $internal ) {
die "Cannot mix -internal and -static\n" if $static;
die "Extra parameters given.\n" if @ARGV;
@source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
glob('ssl/*.c'), glob('ssl/*/*.c') );
} else {
@source = @ARGV;
die "-module isn't useful without -internal\n" if scalar keys %modules > 0;
@source = @ARGV;
}
# Read in the config file
# Data parsed out of the config and state files.
my %hinc; # lib -> header
my %libinc; # header -> lib
my %cskip; # error_file -> lib
my %errorfile; # lib -> error file name
my %fmax; # lib -> max assigned function code
my %rmax; # lib -> max assigned reason code
my %fassigned; # lib -> colon-separated list of assigned function codes
my %rassigned; # lib -> colon-separated list of assigned reason codes
my %fnew; # lib -> count of new function codes
my %rnew; # lib -> count of new reason codes
my %rextra; # "extra" reason code -> lib
my %rcodes; # reason-name -> value
my %ftrans; # old name -> #define-friendly name (all caps)
my %fcodes; # function-name -> value
my $statefile; # state file with assigned reason and function codes
my %strings; # define -> text
open(IN, "<$config") || die "Can't open config file $config";
# Parse config file
while(<IN>)
{
if(/^L\s+(\S+)\s+(\S+)\s+(\S+)/) {
$hinc{$1} = $2;
$libinc{$2} = $1;
$cskip{$3} = $1;
if($3 ne "NONE") {
$csrc{$1} = $3;
$fmax{$1} = 100;
$rmax{$1} = 100;
$fassigned{$1} = ":";
$rassigned{$1} = ":";
$fnew{$1} = 0;
$rnew{$1} = 0;
}
} elsif (/^F\s+(\S+)/) {
# Add extra function with $1
} elsif (/^R\s+(\S+)\s+(\S+)/) {
$rextra{$1} = $2;
$rcodes{$1} = $2;
}
# Read and parse the config file
open(IN, "$config") || die "Can't open config file $config, $!,";
while ( <IN> ) {
next if /^#/ || /^$/;
if ( /^L\s+(\S+)\s+(\S+)\s+(\S+)/ ) {
my $lib = $1;
my $hdr = $2;
my $err = $3;
$hinc{$lib} = $hdr;
$libinc{$hdr} = $lib;
$cskip{$err} = $lib;
next if $err eq 'NONE';
$errorfile{$lib} = $err;
$fmax{$lib} = 100;
$rmax{$lib} = 100;
$fassigned{$lib} = ":";
$rassigned{$lib} = ":";
$fnew{$lib} = 0;
$rnew{$lib} = 0;
} elsif ( /^R\s+(\S+)\s+(\S+)/ ) {
$rextra{$1} = $2;
$rcodes{$1} = $2;
} elsif ( /^S\s+(\S+)/ ) {
$statefile = $1;
} else {
die "Illegal config line $_\n";
}
}
close IN;
# Scan each header file in turn and make a list of error codes
# and function names
while (($hdr, $lib) = each %libinc)
{
next if($hdr eq "NONE");
print STDERR "Scanning header file $hdr\n" if $debug;
my $line = "", $def= "", $linenr = 0, $gotfile = 0, $cpp = 0;
if (open(IN, "<$hdr")) {
$gotfile = 1;
while(<IN>) {
$linenr++;
print STDERR "line: $linenr\r" if $debug;
last if(/BEGIN\s+ERROR\s+CODES/);
if ($line ne '') {
$_ = $line . $_;
$line = '';
}
if (/\\$/) {
$line = $_;
next;
}
if(/\/\*/) {
if (not /\*\//) { # multiline comment...
$line = $_; # ... just accumulate
next;
} else {
s/\/\*.*?\*\///gs; # wipe it
}
}
if ($cpp) {
$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 {} blocks
if (/\{|\/\*/) { # Add a } so editor works...
$line = $_;
} else {
$def .= $_;
}
}
}
print STDERR " \r" if $debug;
$defnr = 0;
# Delete any DECLARE_ macros
$def =~ s/DECLARE_\w+\([\w,\s]+\)//gs;
foreach (split /;/, $def) {
$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;
# Skip over recognized non-function declarations
next if(/typedef\W/ or /DECLARE_STACK_OF/ or /TYPEDEF_.*_OF/);
# Remove STACK_OF(foo)
s/STACK_OF\(\w+\)/void/;
# 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 (/=/)) {
print STDERR "Header $hdr: cannot parse: $_;\n";
}
}
print STDERR " \r" if $debug;
next if $reindex;
# Scan function and reason codes and store them: keep a note of the
# maximum code used.
if ($gotfile) {
while(<IN>) {
if(/^\#\s*define\s+(\S+)\s+(\S+)/) {
$name = $1;
$code = $2;
next if $name =~ /^${lib}err/;
unless($name =~ /^${lib}_([RF])_(\w+)$/) {
print STDERR "Invalid error code $name\n";
next;
}
if($1 eq "R") {
$rcodes{$name} = $code;
if ($rassigned{$lib} =~ /:$code:/) {
print STDERR "!! ERROR: $lib reason code $code assigned twice (collision at $name)\n";
++$errcount;
}
$rassigned{$lib} .= "$code:";
if(!(exists $rextra{$name}) &&
($code > $rmax{$lib}) ) {
$rmax{$lib} = $code;
}
} else {
if ($fassigned{$lib} =~ /:$code:/) {
print STDERR "!! ERROR: $lib function code $code assigned twice (collision at $name)\n";
++$errcount;
}
$fassigned{$lib} .= "$code:";
if($code > $fmax{$lib}) {
$fmax{$lib} = $code;
}
$fcodes{$name} = $code;
}
}
}
}
if ($debug) {
if (defined($fmax{$lib})) {
print STDERR "Max function code fmax" . "{" . "$lib" . "} = $fmax{$lib}\n";
$fassigned{$lib} =~ m/^:(.*):$/;
@fassigned = sort {$a <=> $b} split(":", $1);
print STDERR " @fassigned\n";
}
if (defined($rmax{$lib})) {
print STDERR "Max reason code rmax" . "{" . "$lib" . "} = $rmax{$lib}\n";
$rassigned{$lib} =~ m/^:(.*):$/;
@rassigned = sort {$a <=> $b} split(":", $1);
print STDERR " @rassigned\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";
++$errcount;
print STDERR "\n";
}
}
close IN;
if ( ! $statefile ) {
$statefile = $config;
$statefile =~ s/.ec/.txt/;
}
# The statefile has all the previous assignments.
&phase("Reading state");
my $skippedstate = 0;
if ( ! $reindex && $statefile ) {
open(STATE, "<$statefile") || die "Can't open $statefile, $!";
# Scan function and reason codes and store them: keep a note of the
# maximum code used.
while ( <STATE> ) {
next if /^#/ || /^$/;
my $name;
my $code;
if ( /^(.+):(\d+):\\$/ ) {
$name = $1;
$code = $2;
my $next = <STATE>;
$next =~ s/^\s*(.*)\s*$/$1/;
die "Duplicate define $name" if exists $strings{$name};
$strings{$name} = $next;
} elsif ( /^(\S+):(\d+):(.*)$/ ) {
$name = $1;
$code = $2;
die "Duplicate define $name" if exists $strings{$name};
$strings{$name} = $3;
} else {
die "Bad line in $statefile:\n$_\n";
}
my $lib = $name;
$lib =~ s/^((?:OSSL_|OPENSSL_)?[^_]{2,}).*$/$1/;
$lib = "SSL" if $lib =~ /TLS/;
if ( !defined $errorfile{$lib} ) {
print "Skipping $_";
$skippedstate++;
next;
}
if ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_R_/ ) {
die "$lib reason code $code collision at $name\n"
if $rassigned{$lib} =~ /:$code:/;
$rassigned{$lib} .= "$code:";
if ( !exists $rextra{$name} ) {
$rmax{$lib} = $code if $code > $rmax{$lib};
}
$rcodes{$name} = $code;
} elsif ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_F_/ ) {
die "$lib function code $code collision at $name\n"
if $fassigned{$lib} =~ /:$code:/;
$fassigned{$lib} .= "$code:";
$fmax{$lib} = $code if $code > $fmax{$lib};
$fcodes{$name} = $code;
} else {
die "Bad line in $statefile:\n$_\n";
}
}
close(STATE);
if ( $debug ) {
foreach my $lib ( sort keys %rmax ) {
print STDERR "Reason codes for ${lib}:\n";
if ( $rassigned{$lib} =~ m/^:(.*):$/ ) {
my @rassigned = sort { $a <=> $b } split( ":", $1 );
print STDERR " ", join(' ', @rassigned), "\n";
} else {
print STDERR " --none--\n";
}
}
print STDERR "\n";
foreach my $lib ( sort keys %fmax ) {
print STDERR "Function codes for ${lib}:\n";
if ( $fassigned{$lib} =~ m/^:(.*):$/ ) {
my @fassigned = sort { $a <=> $b } split( ":", $1 );
print STDERR " ", join(' ', @fassigned), "\n";
} else {
print STDERR " --none--\n";
}
}
}
}
# Scan each header file and make a list of error codes
# and function names
&phase("Scanning headers");
while ( ( my $hdr, my $lib ) = each %libinc ) {
next if $hdr eq "NONE";
print STDERR " ." if $debug;
my $line = "";
my $def = "";
my $linenr = 0;
my $cpp = 0;
open(IN, "<$hdr") || die "Can't open $hdr, $!,";
while ( <IN> ) {
$linenr++;
if ( $line ne '' ) {
$_ = $line . $_;
$line = '';
}
if ( /\\$/ ) {
$line = $_;
next;
}
if ( /\/\*/ ) {
if ( not /\*\// ) { # multiline comment...
$line = $_; # ... just accumulate
next;
} else {
s/\/\*.*?\*\///gs; # wipe it
}
}
if ( $cpp ) {
$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 {} blocks
if ( /\{|\/\*/ ) { # Add a so editor works...
$line = $_;
} else {
$def .= $_;
}
}
# Delete any DECLARE_ macros
my $defnr = 0;
$def =~ s/DECLARE_\w+\([\w,\s]+\)//gs;
foreach ( split /;/, $def ) {
$defnr++;
# The goal is to collect function names from function declarations.
s/^[\n\s]*//g;
s/[\n\s]*$//g;
# Skip over recognized non-function declarations
next if /typedef\W/ or /DECLARE_STACK_OF/ or /TYPEDEF_.*_OF/;
# Remove STACK_OF(foo)
s/STACK_OF\(\w+\)/void/;
# 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;
# Last token just before the first () is a function name.
if ( /(\w+)\s*\(\).*/s ) {
my $name = $1;
$name =~ tr/[a-z]/[A-Z]/;
$ftrans{$name} = $1;
} elsif ( /[\(\)]/ and not(/=/) ) {
print STDERR "Header $hdr: cannot parse: $_;\n";
}
}
next if $reindex;
if ( $lib eq "SSL" && $rmax{$lib} >= 1000 ) {
print STDERR "SSL error codes 1000+ are reserved for alerts.\n";
print STDERR "Any new alerts must be added to $config.\n";
$errors++;
}
close IN;
}
print STDERR "\n" if $debug;
# Scan each C source file and look for function and reason codes
# This is done by looking for strings that "look like" function or
# reason codes: basically anything consisting of all upper case and
# numerics which has _F_ or _R_ in it and which has the name of an
# error library at the start. This seems to work fine except for the
# error library at the start. This seems to work fine except for the
# oddly named structure BIO_F_CTX which needs to be ignored.
# If a code doesn't exist in list compiled from headers then mark it
# with the value "X" as a place holder to give it a value later.
# Store all function and reason codes found in %ufcodes and %urcodes
# Store all function and reason codes found in %usedfuncs and %usedreasons
# so all those unreferenced can be printed out.
&phase("Scanning source");
my %usedfuncs;
my %usedreasons;
foreach my $file ( @source ) {
# Don't parse the error source file.
next if exists $cskip{$file};
open( IN, "<$file" ) || die "Can't open $file, $!,";
my $func;
my $linenr = 0;
print STDERR "$file:\n" if $debug;
while ( <IN> ) {
# skip obsoleted source files entirely!
last if /^#error\s+obsolete/;
$linenr++;
if ( !/;$/ && /^\**([a-zA-Z_].*[\s*])?([A-Za-z_0-9]+)\(.*([),]|$)/ ) {
/^([^()]*(\([^()]*\)[^()]*)*)\(/;
$1 =~ /([A-Za-z_0-9]*)$/;
$func = $1;
}
foreach $file (@source) {
# Don't parse the error source file.
next if exists $cskip{$file};
print STDERR "File loaded: ".$file."\r" if $debug;
open(IN, "<$file") || die "Can't open source file $file\n";
my $func;
my $linenr = 0;
while(<IN>) {
# skip obsoleted source files entirely!
last if(/^#error\s+obsolete/);
$linenr++;
if (!/;$/ && /^\**([a-zA-Z_].*[\s*])?([A-Za-z_0-9]+)\(.*([),]|$)/)
{
/^([^()]*(\([^()]*\)[^()]*)*)\(/;
$1 =~ /([A-Za-z_0-9]*)$/;
$func = $1;
}
if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) {
next unless exists $csrc{$2};
next if($1 eq "BIO_F_BUFFER_CTX");
$ufcodes{$1} = 1;
if(!exists $fcodes{$1}) {
$fcodes{$1} = "X";
$fnew{$2}++;
}
$ftrans{$3} = $func unless exists $ftrans{$3};
if (uc $func ne $3) {
print STDERR "ERROR: mismatch $file:$linenr $func:$3\n";
$errcount++;
if ( /(((?:OSSL_|OPENSSL_)?[A-Z0-9]{2,})_F_([A-Z0-9_]+))/ ) {
next unless exists $errorfile{$2};
next if $1 eq "BIO_F_BUFFER_CTX";
$usedfuncs{$1} = 1;
if ( !exists $fcodes{$1} ) {
print STDERR " New function $1\n" if $debug;
$fcodes{$1} = "X";
$fnew{$2}++;
}
print STDERR "Function: $1\t= $fcodes{$1} (lib: $2, name: $3)\n" if $debug;
}
if(/(([A-Z0-9]+)_R_[A-Z0-9_]+)/) {
next unless exists $csrc{$2};
$urcodes{$1} = 1;
if(!exists $rcodes{$1}) {
$rcodes{$1} = "X";
$rnew{$2}++;
}
print STDERR "Reason: $1\t= $rcodes{$1} (lib: $2)\n" if $debug;
}
}
close IN;
$ftrans{$3} = $func unless exists $ftrans{$3};
if ( uc($func) ne $3 ) {
print STDERR "ERROR: mismatch $file:$linenr $func:$3\n";
$errors++;
}
print STDERR " Function $1 = $fcodes{$1}\n"
if $debug;
}
if ( /(((?:OSSL_|OPENSSL_)?[A-Z0-9]{2,})_R_[A-Z0-9_]+)/ ) {
next unless exists $errorfile{$2};
$usedreasons{$1} = 1;
if ( !exists $rcodes{$1} ) {
print STDERR " New reason $1\n" if $debug;
$rcodes{$1} = "X";
$rnew{$2}++;
}
print STDERR " Reason $1 = $rcodes{$1}\n" if $debug;
}
}
close IN;
}
print STDERR " \n" if $debug;
print STDERR "\n" if $debug;
# Now process each library in turn.
&phase("Writing files");
my $newstate = 0;
foreach my $lib ( keys %errorfile ) {
if ( ! $fnew{$lib} && ! $rnew{$lib} ) {
next unless $rebuild;
}
next if scalar keys %modules > 0 && !$modules{$lib};
next if $nowrite;
print STDERR "$lib: $fnew{$lib} new functions\n" if $fnew{$lib};
print STDERR "$lib: $rnew{$lib} new reasons\n" if $rnew{$lib};
$newstate = 1;
foreach $lib (keys %csrc)
{
my $hfile = $hinc{$lib};
my $cfile = $csrc{$lib};
if(!$fnew{$lib} && !$rnew{$lib}) {
next unless $rebuild;
} else {
print STDERR "$lib:\t\t$fnew{$lib} New Functions,";
print STDERR " $rnew{$lib} New Reasons.\n";
next unless $dowrite;
}
# If we get here then we have some new error codes so we
# need to rebuild the header file and C file.
# If we get here then we have some new error codes so we
# need to rebuild the header file and C file.
# Make a sorted list of error and reason codes for later use.
my @function = sort grep( /^${lib}_/, keys %fcodes );
my @reasons = sort grep( /^${lib}_/, keys %rcodes );
# Make a sorted list of error and reason codes for later use.
# indent level for innermost preprocessor lines
my $indent = " ";
my @function = sort grep(/^${lib}_/,keys %fcodes);
my @reasons = sort grep(/^${lib}_/,keys %rcodes);
# Rewrite the header file
# Rewrite the header file
$cpp = 0;
$cplusplus = 0;
if (open(IN, "<$hfile")) {
# Copy across the old file
while(<IN>) {
$cplusplus = $cpp if /^#.*ifdef.*cplusplus/;
$cpp++ if /^#\s*if/;
$cpp-- if /^#\s*endif/;
push @out, $_;
last if (/BEGIN ERROR CODES/);
}
close IN;
} else {
$cpp = 1;
$cplusplus = 1;
push @out,
"/*\n",
" * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.\n",
" *\n",
" * Licensed under the OpenSSL license (the \"License\"). You may not use\n",
" * this file except in compliance with the License. You can obtain a copy\n",
" * in the file LICENSE in the source distribution or at\n",
" * https://www.openssl.org/source/license.html\n",
" */\n",
"\n",
"#ifndef HEADER_${lib}_ERR_H\n",
"# define HEADER_${lib}_ERR_H\n",
"\n",
"# ifdef __cplusplus\n",
"extern \"C\" {\n",
"# endif\n",
"\n",
"/* BEGIN ERROR CODES */\n";
}
open (OUT, ">$hfile") || die "Can't Open File $hfile for writing\n";
print OUT @out;
undef @out;
print OUT <<"EOF";
my $hfile = $hinc{$lib};
$hfile =~ s/.h$/err.h/ if $internal;
open( OUT, ">$hfile" ) || die "Can't write to $hfile, $!,";
print OUT <<"EOF";
/*
* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the \"License\"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
EOF
if($static) {
print OUT <<"EOF";
${staticloader}int ERR_load_${lib}_strings(void);
#ifndef HEADER_${lib}ERR_H
# define HEADER_${lib}ERR_H
EOF
} else {
print OUT <<"EOF";
${staticloader}int ERR_load_${lib}_strings(void);
${staticloader}void ERR_unload_${lib}_strings(void);
${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line);
# define ${lib}err(f,r) ERR_${lib}_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
if ( $internal ) {
# Declare the load function because the generate C file
# includes "fooerr.h" not "foo.h"
if ($lib ne "SSL" && $lib ne "ASYNC"
&& grep { $lib eq uc $_ } @disablables) {
print OUT <<"EOF";
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_${lib}
EOF
}
print OUT <<"EOF";
/* Error codes for the $lib functions. */
/* Function codes. */
$indent = " ";
}
print OUT <<"EOF";
#${indent}ifdef __cplusplus
extern \"C\"
#${indent}endif
int ERR_load_${lib}_strings(void);
EOF
foreach $i (@function) {
$z=48 - length($i);
if($fcodes{$i} eq "X") {
$fassigned{$lib} =~ m/^:([^:]*):/;
$findcode = $1;
if (!defined($findcode)) {
$findcode = $fmax{$lib};
}
while ($fassigned{$lib} =~ m/:$findcode:/) {
$findcode++;
}
$fcodes{$i} = $findcode;
$fassigned{$lib} .= "$findcode:";
print STDERR "New Function code $i\n" if $debug;
}
printf OUT "# define $i%s $fcodes{$i}\n"," " x $z;
}
print OUT "\n/* Reason codes. */\n";
foreach $i (@reasons) {
$z=48 - length($i);
if($rcodes{$i} eq "X") {
$rassigned{$lib} =~ m/^:([^:]*):/;
$findcode = $1;
if (!defined($findcode)) {
$findcode = $rmax{$lib};
}
while ($rassigned{$lib} =~ m/:$findcode:/) {
$findcode++;
}
$rcodes{$i} = $findcode;
$rassigned{$lib} .= "$findcode:";
print STDERR "New Reason code $i\n" if $debug;
}
printf OUT "# define $i%s $rcodes{$i}\n"," " x $z;
}
print OUT <<"EOF";
} else {
print OUT <<"EOF";
# define ${lib}err(f, r) ERR_${lib}_error((f), (r), OPENSSL_FILE, OPENSSL_LINE)
EOF
do {
if ($cplusplus == $cpp) {
print OUT "#", " "x$cpp, "ifdef __cplusplus\n";
print OUT "}\n";
print OUT "#", " "x$cpp, "endif\n";
}
if ($cpp-- > 0) {
print OUT "#", " "x$cpp, "endif\n";
}
} while ($cpp);
close OUT;
if ( ! $static ) {
print OUT <<"EOF";
# Rewrite the C source file containing the error details.
# ifdef __cplusplus
extern \"C\" {
# endif
int ERR_load_${lib}_strings(void);
void ERR_unload_${lib}_strings(void);
void ERR_${lib}_error(int function, int reason, char *file, int line);
# ifdef __cplusplus
}
# endif
EOF
}
}
# First, read any existing reason string definitions:
my %err_reason_strings;
if (open(IN,"<$cfile")) {
my $line = "";
while (<IN>) {
s|\R$||; # Better chomp
$_ = $line . $_;
$line = "";
if (/{ERR_(FUNC|REASON)\(/) {
if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) {
$err_reason_strings{$1} = $2;
} elsif (/\b${lib}_F_(\w*)\b.*\"(.*)\"/) {
if (!exists $ftrans{$1} && ($1 ne $2)) {
print STDERR "WARNING: Mismatched function string $2\n";
$ftrans{$1} = $2;
}
} else {
$line = $_;
}
}
}
close(IN);
}
print OUT "\n/*\n * $lib function codes.\n */\n";
foreach my $i ( @function ) {
my $z = 48 - length($i);
$z = 0 if $z < 0;
if ( $fcodes{$i} eq "X" ) {
$fassigned{$lib} =~ m/^:([^:]*):/;
my $findcode = $1;
$findcode = $fmax{$lib} if !defined $findcode;
while ( $fassigned{$lib} =~ m/:$findcode:/ ) {
$findcode++;
}
$fcodes{$i} = $findcode;
$fassigned{$lib} .= "$findcode:";
print STDERR "New Function code $i\n" if $debug;
}
printf OUT "#${indent}define $i%s $fcodes{$i}\n", " " x $z;
}
print OUT "\n/*\n * $lib reason codes.\n */\n";
foreach my $i ( @reasons ) {
my $z = 48 - length($i);
$z = 0 if $z < 0;
if ( $rcodes{$i} eq "X" ) {
$rassigned{$lib} =~ m/^:([^:]*):/;
my $findcode = $1;
$findcode = $rmax{$lib} if !defined $findcode;
while ( $rassigned{$lib} =~ m/:$findcode:/ ) {
$findcode++;
}
$rcodes{$i} = $findcode;
$rassigned{$lib} .= "$findcode:";
print STDERR "New Reason code $i\n" if $debug;
}
printf OUT "#${indent}define $i%s $rcodes{$i}\n", " " x $z;
}
print OUT "\n";
my $hincf;
if($static) {
$hincf = $hfile;
$hincf =~ s|.*include/||;
if ($hincf =~ m|^openssl/|) {
$hincf = "<${hincf}>";
} else {
$hincf = "\"${hincf}\"";
}
} else {
$hincf = "\"$hfile\"";
}
while (length($indent) > 0) {
$indent = substr $indent, 0, -1;
print OUT "#${indent}endif\n";
}
# If static we know the error code at compile time so use it
# in error definitions.
# Rewrite the C source file containing the error details.
if ($static)
{
$pack_errcode = "ERR_LIB_${lib}";
$load_errcode = "0";
}
else
{
$pack_errcode = "0";
$load_errcode = "ERR_LIB_${lib}";
}
# First, read any existing reason string definitions:
my $cfile = $errorfile{$lib};
my $pack_lib = $internal ? "ERR_LIB_${lib}" : "0";
my $hincf = $hfile;
$hincf =~ s|.*include/||;
if ( $hincf =~ m|^openssl/| ) {
$hincf = "<${hincf}>";
} else {
$hincf = "\"${hincf}\"";
}
open( OUT, ">$cfile" )
|| die "Can't open $cfile for writing, $!, stopped";
open (OUT,">$cfile") || die "Can't open $cfile for writing";
my $const = $internal ? 'const ' : '';
print OUT <<"EOF";
print OUT <<"EOF";
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
@@ -595,177 +567,187 @@ EOF
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <openssl/err.h>
#include $hincf
/* 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[] = {
static ${const}ERR_STRING_DATA ${lib}_str_functs[] = {
EOF
# Add each function code: if a function name is found then use it.
foreach $i (@function) {
my $fn;
$i =~ /^${lib}_F_(\S+)$/;
$fn = $1;
if(exists $ftrans{$fn}) {
$fn = $ftrans{$fn};
}
# print OUT "{ERR_PACK($pack_errcode,$i,0),\t\"$fn\"},\n";
if(length($i) + length($fn) > 57) {
print OUT " {ERR_FUNC($i),\n \"$fn\"},\n";
} else {
print OUT " {ERR_FUNC($i), \"$fn\"},\n";
}
}
print OUT <<"EOF";
# Add each function code: if a function name is found then use it.
foreach my $i ( @function ) {
my $fn;
if ( exists $strings{$i} and $strings{$i} ne '' ) {
$fn = $strings{$i};
$fn = "" if $fn eq '*';
} else {
$i =~ /^${lib}_F_(\S+)$/;
$fn = $1;
$fn = $ftrans{$fn} if exists $ftrans{$fn};
$strings{$i} = $fn;
}
my $short = " {ERR_PACK($pack_lib, $i, 0), \"$fn\"},";
if ( length($short) <= 80 ) {
print OUT "$short\n";
} else {
print OUT " {ERR_PACK($pack_lib, $i, 0),\n \"$fn\"},\n";
}
}
print OUT <<"EOF";
{0, NULL}
};
static ERR_STRING_DATA ${lib}_str_reasons[] = {
static ${const}ERR_STRING_DATA ${lib}_str_reasons[] = {
EOF
# Add each reason code.
foreach $i (@reasons) {
my $rn;
my $rstr = "ERR_REASON($i)";
if (exists $err_reason_strings{$i}) {
$rn = $err_reason_strings{$i};
} else {
$i =~ /^${lib}_R_(\S+)$/;
$rn = $1;
$rn =~ tr/_[A-Z]/ [a-z]/;
}
if(length($i) + length($rn) > 55) {
print OUT " {${rstr},\n \"$rn\"},\n";
} else {
print OUT " {${rstr}, \"$rn\"},\n";
}
}
if($static) {
print OUT <<"EOF";
# Add each reason code.
foreach my $i ( @reasons ) {
my $rn;
if ( exists $strings{$i} ) {
$rn = $strings{$i};
$rn = "" if $rn eq '*';
} else {
$i =~ /^${lib}_R_(\S+)$/;
$rn = $1;
$rn =~ tr/_[A-Z]/ [a-z]/;
$strings{$i} = $rn;
}
my $short = " {ERR_PACK($pack_lib, 0, $i), \"$rn\"},";
if ( length($short) <= 80 ) {
print OUT "$short\n";
} else {
print OUT " {ERR_PACK($pack_lib, 0, $i),\n \"$rn\"},\n";
}
}
print OUT <<"EOF";
{0, NULL}
};
#endif
EOF
if ( $internal ) {
print OUT <<"EOF";
${staticloader}int ERR_load_${lib}_strings(void)
int ERR_load_${lib}_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(${lib}_str_functs[0].error) == NULL) {
ERR_load_strings($load_errcode, ${lib}_str_functs);
ERR_load_strings($load_errcode, ${lib}_str_reasons);
ERR_load_strings_const(${lib}_str_functs);
ERR_load_strings_const(${lib}_str_reasons);
}
#endif
return 1;
}
EOF
} else {
print OUT <<"EOF";
{0, NULL}
};
} else {
my $st = $static ? "static " : "";
print OUT <<"EOF";
#endif
static int lib_code = 0;
static int error_loaded = 0;
#ifdef ${lib}_LIB_NAME
static ERR_STRING_DATA ${lib}_lib_name[] = {
{0, ${lib}_LIB_NAME},
{0, NULL}
};
#endif
static int ${lib}_lib_error_code = 0;
static int ${lib}_error_init = 1;
${staticloader}int ERR_load_${lib}_strings(void)
${st}int ERR_load_${lib}_strings(void)
{
if (${lib}_lib_error_code == 0)
${lib}_lib_error_code = ERR_get_next_error_library();
if (lib_code == 0)
lib_code = ERR_get_next_error_library();
if (${lib}_error_init) {
${lib}_error_init = 0;
if (!error_loaded) {
#ifndef OPENSSL_NO_ERR
ERR_load_strings(${lib}_lib_error_code, ${lib}_str_functs);
ERR_load_strings(${lib}_lib_error_code, ${lib}_str_reasons);
#endif
#ifdef ${lib}_LIB_NAME
${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code, 0, 0);
ERR_load_strings(0, ${lib}_lib_name);
ERR_load_strings(lib_code, ${lib}_str_functs);
ERR_load_strings(lib_code, ${lib}_str_reasons);
#endif
error_loaded = 1;
}
return 1;
}
${staticloader}void ERR_unload_${lib}_strings(void)
${st}void ERR_unload_${lib}_strings(void)
{
if (${lib}_error_init == 0) {
if (error_loaded) {
#ifndef OPENSSL_NO_ERR
ERR_unload_strings(${lib}_lib_error_code, ${lib}_str_functs);
ERR_unload_strings(${lib}_lib_error_code, ${lib}_str_reasons);
ERR_unload_strings(lib_code, ${lib}_str_functs);
ERR_unload_strings(lib_code, ${lib}_str_reasons);
#endif
#ifdef ${lib}_LIB_NAME
ERR_unload_strings(0, ${lib}_lib_name);
#endif
${lib}_error_init = 1;
error_loaded = 0;
}
}
${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line)
${st}void ERR_${lib}_error(int function, int reason, char *file, int line)
{
if (${lib}_lib_error_code == 0)
${lib}_lib_error_code = ERR_get_next_error_library();
ERR_PUT_error(${lib}_lib_error_code, function, reason, file, line);
if (lib_code == 0)
lib_code = ERR_get_next_error_library();
ERR_PUT_error(lib_code, function, reason, file, line);
}
EOF
}
close OUT;
}
close OUT;
undef %err_reason_strings;
}
if($debug && %notrans) {
print STDERR "The following function codes were not translated:\n";
foreach(sort keys %notrans)
{
print STDERR "$_\n";
}
}
&phase("Ending");
# Make a list of unreferenced function and reason codes
foreach (keys %fcodes) {
push (@funref, $_) unless exists $ufcodes{$_};
if ( $unref ) {
my @funref;
foreach ( keys %fcodes ) {
push( @funref, $_ ) unless exists $usedfuncs{$_};
}
my @runref;
foreach ( keys %rcodes ) {
push( @runref, $_ ) unless exists $usedreasons{$_};
}
if ( @funref ) {
print STDERR "The following function codes were not referenced:\n";
foreach ( sort @funref ) {
print STDERR " $_\n";
}
}
if ( @runref ) {
print STDERR "The following reason codes were not referenced:\n";
foreach ( sort @runref ) {
print STDERR " $_\n";
}
}
}
foreach (keys %rcodes) {
push (@runref, $_) unless exists $urcodes{$_};
}
if($unref && @funref) {
print STDERR "The following function codes were not referenced:\n";
foreach(sort @funref)
{
print STDERR "$_\n";
}
}
if($unref && @runref) {
print STDERR "The following reason codes were not referenced:\n";
foreach(sort @runref)
{
print STDERR "$_\n";
}
}
if($errcount) {
print STDERR "There were errors, failing...\n\n";
exit $errcount;
die "Found $errors errors, quitting" if $errors;
# Update the state file
if ( $newstate ) {
open(OUT, ">$statefile.new")
|| die "Can't write $statefile.new, $!";
print OUT <<"EOF";
# Copyright 1999-$YEAR The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
EOF
print OUT "\n# Function codes\n";
foreach my $i ( sort keys %fcodes ) {
my $short = "$i:$fcodes{$i}:";
my $t = exists $strings{$i} ? $strings{$i} : "";
$t = "\\\n\t" . $t if length($short) + length($t) > 80;
print OUT "$short$t\n";
}
print OUT "\n#Reason codes\n";
foreach my $i ( sort keys %rcodes ) {
my $short = "$i:$rcodes{$i}:";
my $t = exists $strings{$i} ? "$strings{$i}" : "";
$t = "\\\n\t" . $t if length($short) + length($t) > 80;
print OUT "$short$t\n" if !exists $rextra{$i};
}
close(OUT);
if ( $skippedstate ) {
print "Skipped state, leaving update in $statefile.new";
} else {
rename "$statefile", "$statefile.old"
|| die "Can't backup $statefile to $statefile.old, $!";
rename "$statefile.new", "$statefile"
|| die "Can't rename $statefile to $statefile.new, $!";
}
}
exit;