summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2020-03-11 12:24:33 -0600
committerKarl Williamson <khw@cpan.org>2020-03-18 14:29:46 -0600
commit5baa389e84c8348c7335cd8e58d1a2f6f917f7e4 (patch)
tree9c680609ae48e379e7f855f03d4b9613d664682c
parent5f47881659a0e7bfbe5db3cda32beec498c07696 (diff)
downloadperl-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.c41
-rw-r--r--reentr.h22
-rw-r--r--regen/reentr.pl50
3 files changed, 107 insertions, 6 deletions
diff --git a/reentr.c b/reentr.c
index ede96a9d18..10c2d88655 100644
--- a/reentr.c
+++ b/reentr.c
@@ -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:
diff --git a/reentr.h b/reentr.h
index 9e65001dcb..25f21ad1a6 100644
--- a/reentr.h
+++ b/reentr.h
@@ -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: