| #! /usr/bin/env perl | |
| # Copyright 2018-2019 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 | |
| use strict; | |
| no strict 'refs'; # To be able to use strings as function refs | |
| use OpenSSL::Test; | |
| use OpenSSL::Test::Utils; | |
| use Errno qw(:POSIX); | |
| use POSIX qw(strerror); | |
| # We actually have space for up to 4095 error messages, | |
| # numerically speaking... but we're currently only using | |
| # numbers 1 through 127. | |
| # This constant should correspond to the same constant | |
| # defined in crypto/err/err.c, or at least must not be | |
| # assigned a greater number. | |
| use constant NUM_SYS_STR_REASONS => 127; | |
| setup('test_errstr'); | |
| # In a cross compiled situation, there are chances that our | |
| # application is linked against different C libraries than | |
| # perl, and may thereby get different error messages for the | |
| # same error. | |
| # The safest is not to test under such circumstances. | |
| plan skip_all => 'This is unsupported for cross compiled configurations' | |
| if config('CROSS_COMPILE'); | |
| # The same can be said when compiling OpenSSL with mingw configuration | |
| # on Windows when built with msys perl. Similar problems are also observed | |
| # in MSVC builds, depending on the perl implementation used. | |
| plan skip_all => 'This is unsupported on MSYS/MinGW or MSWin32' | |
| if $^O eq 'msys' or $^O eq 'MSWin32'; | |
| plan skip_all => 'OpenSSL is configured "no-autoerrinit" or "no-err"' | |
| if disabled('autoerrinit') || disabled('err'); | |
| # These are POSIX error names, which Errno implements as functions | |
| # (this is documented) | |
| my @posix_errors = @{$Errno::EXPORT_TAGS{POSIX}}; | |
| if ($^O eq 'MSWin32') { | |
| # On Windows, these errors have been observed to not always be loaded by | |
| # apps/openssl, while they are in perl, which causes a difference that we | |
| # consider a false alarm. So we skip checking these errors. | |
| # Because we can't know exactly what symbols exist in a perticular perl | |
| # version, we resort to discovering them directly in the Errno package | |
| # symbol table. | |
| my @error_skiplist = qw( | |
| ENETDOWN | |
| ENETUNREACH | |
| ENETRESET | |
| ECONNABORTED | |
| EISCONN | |
| ENOTCONN | |
| ESHUTDOWN | |
| ETOOMANYREFS | |
| ETIMEDOUT | |
| EHOSTDOWN | |
| EHOSTUNREACH | |
| EALREADY | |
| EINPROGRESS | |
| ESTALE | |
| EUCLEAN | |
| ENOTNAM | |
| ENAVAIL | |
| ENOMEDIUM | |
| ENOKEY | |
| ); | |
| @posix_errors = | |
| grep { | |
| my $x = $_; | |
| ! grep { | |
| exists $Errno::{$_} && $x == $Errno::{$_} | |
| } @error_skiplist | |
| } @posix_errors; | |
| } | |
| plan tests => scalar @posix_errors | |
| +1 # Checking that error 128 gives 'reason(128)' | |
| +1 # Checking that error 0 gives the library name | |
| ; | |
| foreach my $errname (@posix_errors) { | |
| my $errnum = "Errno::$errname"->(); | |
| SKIP: { | |
| skip "Error $errname ($errnum) isn't within our range", 1 | |
| if $errnum > NUM_SYS_STR_REASONS; | |
| my $perr = eval { | |
| # Set $! to the error number... | |
| local $! = $errnum; | |
| # ... and $! will give you the error string back | |
| $! | |
| }; | |
| # We know that the system reasons are in OpenSSL error library 2 | |
| my @oerr = run(app([ qw(openssl errstr), sprintf("2%06x", $errnum) ]), | |
| capture => 1); | |
| $oerr[0] =~ s|\R$||; | |
| $oerr[0] =~ s|.*system library:||g; # The actual message is last | |
| ok($oerr[0] eq $perr, "($errnum) '$oerr[0]' == '$perr'"); | |
| } | |
| } | |
| my @after = run(app([ qw(openssl errstr 2000080) ]), capture => 1); | |
| $after[0] =~ s|\R$||; | |
| $after[0] =~ s|.*system library:||g; | |
| ok($after[0] eq "reason(128)", "(128) '$after[0]' == 'reason(128)'"); | |
| my @zero = run(app([ qw(openssl errstr 2000000) ]), capture => 1); | |
| $zero[0] =~ s|\R$||; | |
| $zero[0] =~ s|.*system library:||g; | |
| ok($zero[0] eq "system library", "(0) '$zero[0]' == 'system library'"); |