diff options
author | Karl Williamson <khw@cpan.org> | 2020-03-11 12:24:33 -0600 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2020-03-18 14:29:46 -0600 |
commit | 5baa389e84c8348c7335cd8e58d1a2f6f917f7e4 (patch) | |
tree | 9c680609ae48e379e7f855f03d4b9613d664682c | |
parent | 5f47881659a0e7bfbe5db3cda32beec498c07696 (diff) | |
download | perl-5baa389e84c8348c7335cd8e58d1a2f6f917f7e4.tar.gz |
reentr.c: Handle getspnam()
This has never worked to increase the buffer size if necessary.
Apparently the default has always been big enough. But this commit
fixes it to retry if too small.
I don't think there is a way to write tests for this. getspnam is
called only as a small part of pp_gpwent, and is not part of the API,
and is called only when run as root.
I did test it on my box, with gdb, starting with a buffer size of 1, and
single stepping and observing that it works as I expected.
-rw-r--r-- | reentr.c | 41 | ||||
-rw-r--r-- | reentr.h | 22 | ||||
-rw-r--r-- | regen/reentr.pl | 50 |
3 files changed, 107 insertions, 6 deletions
@@ -381,6 +381,16 @@ Perl_reentrant_retry(const char *f, ...) #endif if (key == 0) { + +#ifdef HAS_GETSPNAM_R + + /* This is a #define as has no corresponding keyword */ + if (strEQ(f, "getspnam")) { + key = KEY_getspnam; + } + +#endif + } else if (key < 0) { key = -key; @@ -510,9 +520,9 @@ Perl_reentrant_retry(const char *f, ...) # endif # ifdef USE_PWENT_BUFFER - case KEY_getpwnam: - case KEY_getpwuid: - case KEY_getpwent: + case KEY_getpwnam: + case KEY_getpwuid: + case KEY_getpwent: { # ifdef PERL_REENTRANT_MAXSIZE @@ -551,6 +561,31 @@ Perl_reentrant_retry(const char *f, ...) break; # endif +# ifdef USE_SPENT_BUFFER + + case KEY_getspnam: + { + char * name; + +# ifdef PERL_REENTRANT_MAXSIZE + if (PL_reentrant_buffer->_spent_size <= + PERL_REENTRANT_MAXSIZE / 2) + +# endif + RenewDouble(PL_reentrant_buffer->_spent_buffer, + &PL_reentrant_buffer->_spent_size, char); + switch (key) { + case KEY_getspnam: + name = va_arg(ap, char *); + retptr = getspnam(name); break; + default: + SETERRNO(ERANGE, LIB_INVARG); + break; + } + } + break; + +# endif # ifdef USE_PROTOENT_BUFFER case KEY_getprotobyname: @@ -357,6 +357,22 @@ # undef USE_PWENT_BUFFER # endif +/* The getspent getspnam using buffer? */ + +# if defined(HAS_GETSPNAM_R) && (GETSPNAM_R_PROTO == REENTRANT_PROTO_I_CSBWR || GETSPNAM_R_PROTO == REENTRANT_PROTO_S_CSBI) +# define GETSPNAM_R_HAS_BUFFER +# else +# undef GETSPNAM_R_HAS_BUFFER +# endif + +/* Any of the getspent getspnam using buffer? */ + +# if (defined(GETSPENT_R_HAS_BUFFER) || defined(GETSPNAM_R_HAS_BUFFER)) +# define USE_SPENT_BUFFER +# else +# undef USE_SPENT_BUFFER +# endif + /* The gethostent gethostbyaddr gethostbyname using ptr? */ # if defined(HAS_GETHOSTENT_R) && (GETHOSTENT_R_PROTO == REENTRANT_PROTO_I_SBWRE) @@ -1495,6 +1511,12 @@ typedef struct { + +/* Special case this; if others came along, could automate it */ +# ifdef HAS_GETSPNAM_R +# define KEY_getspnam -1 +# endif + #endif /* USE_REENTRANT_API */ #endif diff --git a/regen/reentr.pl b/regen/reentr.pl index 5fe887d9a0..e672bb5233 100644 --- a/regen/reentr.pl +++ b/regen/reentr.pl @@ -434,6 +434,9 @@ define('FPTR', 'H', define('BUFFER', 'B', qw(getpwent getpwgid getpwnam)); +define('BUFFER', 'B', + qw(getspent getspnam)); + define('PTR', 'R', qw(gethostent gethostbyaddr gethostbyname)); define('PTR', 'R', @@ -739,6 +742,12 @@ typedef struct { /* The wrappers. */ @wrap + +/* Special case this; if others came along, could automate it */ +# ifdef HAS_GETSPNAM_R +# define KEY_getspnam -1 +# endif + #endif /* USE_REENTRANT_API */ #endif @@ -860,6 +869,16 @@ Perl_reentrant_retry(const char *f, ...) #endif if (key == 0) { + +#ifdef HAS_GETSPNAM_R + + /* This is a #define as has no corresponding keyword */ + if (strEQ(f, "getspnam")) { + key = KEY_getspnam; + } + +#endif + } else if (key < 0) { key = -key; @@ -989,9 +1008,9 @@ Perl_reentrant_retry(const char *f, ...) # endif # ifdef USE_PWENT_BUFFER - case KEY_getpwnam: - case KEY_getpwuid: - case KEY_getpwent: + case KEY_getpwnam: + case KEY_getpwuid: + case KEY_getpwent: { # ifdef PERL_REENTRANT_MAXSIZE @@ -1030,6 +1049,31 @@ Perl_reentrant_retry(const char *f, ...) break; # endif +# ifdef USE_SPENT_BUFFER + + case KEY_getspnam: + { + char * name; + +# ifdef PERL_REENTRANT_MAXSIZE + if (PL_reentrant_buffer->_spent_size <= + PERL_REENTRANT_MAXSIZE / 2) + +# endif + RenewDouble(PL_reentrant_buffer->_spent_buffer, + &PL_reentrant_buffer->_spent_size, char); + switch (key) { + case KEY_getspnam: + name = va_arg(ap, char *); + retptr = getspnam(name); break; + default: + SETERRNO(ERANGE, LIB_INVARG); + break; + } + } + break; + +# endif # ifdef USE_PROTOENT_BUFFER case KEY_getprotobyname: |