From: Ulrich Drepper Date: Fri, 30 Jan 1998 17:23:34 +0000 (+0000) Subject: Correct handling of enlarging buffers (clear errno). X-Git-Tag: cvs/before-sparc-2_0_x-branch~242 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00d6b1b9cd5a263c057ffa048fccc3fd3743b5a9;p=thirdparty%2Fglibc.git Correct handling of enlarging buffers (clear errno). --- diff --git a/grp/fgetgrent.c b/grp/fgetgrent.c index 0b461ad5fea..03b9d046bac 100644 --- a/grp/fgetgrent.c +++ b/grp/fgetgrent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -33,7 +33,7 @@ fgetgrent (FILE *stream) static size_t buffer_size; static struct group resbuf; struct group *result; - int save; + int save, save_errno; /* Get lock. */ __libc_lock_lock (lock); @@ -45,12 +45,16 @@ fgetgrent (FILE *stream) buffer = malloc (buffer_size); } + /* We don't want to pass errno == 0 or errno == ERANGE back */ + save_errno = errno; + while (buffer != NULL && __fgetgrent_r (stream, &resbuf, buffer, buffer_size, &result) != 0 && errno == ERANGE) { char *new_buf; buffer_size += NSS_BUFLEN_GROUP; + __set_errno (0); new_buf = realloc (buffer, buffer_size); if (new_buf == NULL) { @@ -63,6 +67,9 @@ fgetgrent (FILE *stream) buffer = new_buf; } + if (errno == 0) + __set_errno (save_errno); + if (buffer == NULL) result = NULL; diff --git a/grp/initgroups.c b/grp/initgroups.c index 2ca90ab18d1..3cdc3ed484c 100644 --- a/grp/initgroups.c +++ b/grp/initgroups.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1989, 1991, 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1989, 91, 93, 96, 97, 98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -47,6 +47,7 @@ initgroups (user, group) size_t ngroups; gid_t *groups; int status; + int save_errno; #ifdef NGROUPS_MAX # define limit NGROUPS_MAX @@ -68,6 +69,7 @@ initgroups (user, group) n = 0; groups[n++] = group; + save_errno = errno; do { @@ -76,6 +78,7 @@ initgroups (user, group) { buflen *= 2; tmpbuf = __alloca (buflen); + __set_errno (0); } if (status == 0 && g->gr_gid != group) @@ -108,6 +111,7 @@ initgroups (user, group) while (status == 0); done: + __set_errno (save_errno); endgrent (); return setgroups (n, groups); diff --git a/inet/rcmd.c b/inet/rcmd.c index 6a680c18b72..121cd19302f 100644 --- a/inet/rcmd.c +++ b/inet/rcmd.c @@ -74,11 +74,14 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p) int s, lport, timo; char c; int herr; + int save_errno; pid = getpid(); hstbuflen = 1024; tmphstbuf = __alloca (hstbuflen); + save_errno = errno; + while (__gethostbyname_r (*ahost, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr) < 0) if (herr != NETDB_INTERNAL || errno != ERANGE) @@ -92,8 +95,10 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p) /* Enlarge the buffer. */ hstbuflen *= 2; tmphstbuf = __alloca (hstbuflen); + __set_errno (0); } + __set_errno (save_errno); *ahost = hp->h_name; oldmask = sigblock(sigmask(SIGURG)); for (timo = 1, lport = IPPORT_RESERVED - 1;;) { @@ -264,9 +269,11 @@ ruserok(rhost, superuser, ruser, luser) u_int32_t addr; char **ap; int herr; + int save_errno; buflen = 1024; buffer = __alloca (buflen); + save_errno = errno; while (__gethostbyname_r (rhost, &hostbuf, buffer, buflen, &hp, &herr) < 0) @@ -277,8 +284,11 @@ ruserok(rhost, superuser, ruser, luser) /* Enlarge the buffer. */ buflen *= 2; buffer = __alloca (buflen); + __set_errno (0); } + __set_errno (save_errno); + for (ap = hp->h_addr_list; *ap; ++ap) { bcopy(*ap, &addr, sizeof(addr)); if (iruserok(addr, superuser, ruser, luser) == 0) @@ -436,6 +446,7 @@ __icheckhost(raddr, lhost) register u_int32_t laddr; register char **pp; int herr; + int save_errno; /* Try for raw ip address first. */ if (isdigit(*lhost) && (int32_t)(laddr = inet_addr(lhost)) != -1) @@ -444,6 +455,8 @@ __icheckhost(raddr, lhost) /* Better be a hostname. */ buflen = 1024; buffer = __alloca (buflen); + save_errno = errno; + while (__gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr) < 0) if (herr != NETDB_INTERNAL || errno != ERANGE) @@ -453,8 +466,11 @@ __icheckhost(raddr, lhost) /* Enlarge the buffer. */ buflen *= 2; buffer = __alloca (buflen); + __set_errno (0); } + __set_errno (save_errno); + /* Spin through ip addresses. */ for (pp = hp->h_addr_list; *pp; ++pp) if (!bcmp(&raddr, *pp, sizeof(u_int32_t))) diff --git a/inet/rexec.c b/inet/rexec.c index 72df066b03e..cd8343c8b97 100644 --- a/inet/rexec.c +++ b/inet/rexec.c @@ -64,9 +64,12 @@ rexec(ahost, rport, name, pass, cmd, fd2p) int s, timo = 1, s3; char c; int herr; + int save_errno; hstbuflen = 1024; hsttmpbuf = __alloca (hstbuflen); + save_errno = errno; + while (__gethostbyname_r (*ahost, &hostbuf, hsttmpbuf, hstbuflen, &hp, &herr) < 0) if (herr != NETDB_INTERNAL || errno != ERANGE) @@ -80,8 +83,10 @@ rexec(ahost, rport, name, pass, cmd, fd2p) /* Enlarge the buffer. */ hstbuflen *= 2; hsttmpbuf = __alloca (hstbuflen); + __set_errno (0); } + __set_errno (save_errno); *ahost = hp->h_name; ruserpass(hp->h_name, &name, &pass); retry: diff --git a/nss/getXXbyYY.c b/nss/getXXbyYY.c index f81df053816..077d0d70b71 100644 --- a/nss/getXXbyYY.c +++ b/nss/getXXbyYY.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -79,7 +79,7 @@ FUNCTION_NAME (ADD_PARAMS) static size_t buffer_size; static LOOKUP_TYPE resbuf; LOOKUP_TYPE *result; - int save; + int save, save_errno; #ifdef NEED_H_ERRNO int h_errno_tmp = 0; #endif @@ -100,6 +100,9 @@ FUNCTION_NAME (ADD_PARAMS) #endif } + /* We don't want to pass errno == 0 or errno == ERANGE back */ + save_errno = errno; + while (buffer != NULL && INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, &resbuf, buffer, buffer_size, &result H_ERRNO_VAR) != 0 @@ -110,6 +113,7 @@ FUNCTION_NAME (ADD_PARAMS) { char *new_buf; buffer_size += BUFLEN; + __set_errno (0); new_buf = realloc (buffer, buffer_size); if (new_buf == NULL) { @@ -122,6 +126,9 @@ FUNCTION_NAME (ADD_PARAMS) buffer = new_buf; } + if (errno == 0) + __set_errno (save_errno); + if (buffer == NULL) result = NULL; diff --git a/nss/getXXent.c b/nss/getXXent.c index eeb03dfa37c..d93f9fa04b1 100644 --- a/nss/getXXent.c +++ b/nss/getXXent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -70,7 +70,7 @@ GETFUNC_NAME (void) static size_t buffer_size; static LOOKUP_TYPE resbuf; LOOKUP_TYPE *result; - int save; + int save, save_errno; /* Get lock. */ __libc_lock_lock (lock); @@ -81,6 +81,9 @@ GETFUNC_NAME (void) buffer = malloc (buffer_size); } + /* We don't want to pass errno == 0 or errno == ERANGE back */ + save_errno = errno; + while (buffer != NULL && INTERNAL (REENTRANT_GETNAME) (&resbuf, buffer, buffer_size, &result H_ERRNO_VAR) != 0 @@ -91,6 +94,7 @@ GETFUNC_NAME (void) { char *new_buf; buffer_size += BUFLEN; + __set_errno (0); new_buf = realloc (buffer, buffer_size); if (new_buf == NULL) { @@ -103,6 +107,9 @@ GETFUNC_NAME (void) buffer = new_buf; } + if (errno == 0) + __set_errno (save_errno); + if (buffer == NULL) result = NULL; diff --git a/pwd/fgetpwent.c b/pwd/fgetpwent.c index 63f62fcf6d4..d076f347021 100644 --- a/pwd/fgetpwent.c +++ b/pwd/fgetpwent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -33,7 +33,7 @@ fgetpwent (FILE *stream) static size_t buffer_size; static struct passwd resbuf; struct passwd *result; - int save; + int save, save_errno; /* Get lock. */ __libc_lock_lock (lock); @@ -45,12 +45,16 @@ fgetpwent (FILE *stream) buffer = malloc (buffer_size); } + /* We don't want to pass errno == 0 or errno == ERANGE back */ + save_errno = errno; + while (buffer != NULL && __fgetpwent_r (stream, &resbuf, buffer, buffer_size, &result) != 0 && errno == ERANGE) { char *new_buf; buffer_size += NSS_BUFLEN_PASSWD; + __set_errno (0); new_buf = realloc (buffer, buffer_size); if (new_buf == NULL) { @@ -63,6 +67,9 @@ fgetpwent (FILE *stream) buffer = new_buf; } + if (errno == 0) + __set_errno (save_errno); + if (buffer == NULL) result = NULL; diff --git a/shadow/fgetspent.c b/shadow/fgetspent.c index bd54c7e5959..b569744d620 100644 --- a/shadow/fgetspent.c +++ b/shadow/fgetspent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -36,7 +36,7 @@ fgetspent (FILE *stream) static size_t buffer_size; static struct spwd resbuf; struct spwd *result; - int save; + int save, save_errno; /* Get lock. */ __libc_lock_lock (lock); @@ -48,12 +48,15 @@ fgetspent (FILE *stream) buffer = malloc (buffer_size); } + /* We don't want to pass errno == 0 or errno == ERANGE back */ + save_errno = errno; while (buffer != NULL && __fgetspent_r (stream, &resbuf, buffer, buffer_size, &result) != 0 && errno == ERANGE) { char *new_buf; buffer_size += BUFLEN_SPWD; + __set_errno (0); new_buf = realloc (buffer, buffer_size); if (new_buf == NULL) { @@ -66,6 +69,9 @@ fgetspent (FILE *stream) buffer = new_buf; } + if (errno == 0) + __set_errno (save_errno); + if (buffer == NULL) result = NULL; diff --git a/shadow/sgetspent.c b/shadow/sgetspent.c index ecfe01ed1d1..95225614d09 100644 --- a/shadow/sgetspent.c +++ b/shadow/sgetspent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -36,7 +36,7 @@ sgetspent (const char *string) static size_t buffer_size; static struct spwd resbuf; struct spwd *result; - int save; + int save, save_errno; /* Get lock. */ __libc_lock_lock (lock); @@ -48,12 +48,15 @@ sgetspent (const char *string) buffer = malloc (buffer_size); } + /* We don't want to pass errno == 0 or errno == ERANGE back */ + save_errno = errno; while (buffer != NULL && __sgetspent_r (string, &resbuf, buffer, buffer_size, &result) != 0 && errno == ERANGE) { char *new_buf; buffer_size += BUFLEN_SPWD; + __set_errno (0); new_buf = realloc (buffer, buffer_size); if (new_buf == NULL) { @@ -66,6 +69,9 @@ sgetspent (const char *string) buffer = new_buf; } + if (errno == 0) + __set_errno (save_errno); + if (buffer == NULL) result = NULL; diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c index d7b949caa69..45266c4dc84 100644 --- a/sunrpc/clnt_gen.c +++ b/sunrpc/clnt_gen.c @@ -63,9 +63,11 @@ clnt_create(hostname, prog, vers, proto) struct timeval tv; CLIENT *client; int herr; + int save_errno; hstbuflen = 1024; hsttmpbuf = __alloca (hstbuflen); + save_errno = errno; while (__gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen, &h, &herr) < 0) if (herr != NETDB_INTERNAL || errno != ERANGE) @@ -78,8 +80,12 @@ clnt_create(hostname, prog, vers, proto) /* Enlarge the buffer. */ hstbuflen *= 2; hsttmpbuf = __alloca (hstbuflen); + __set_errno (0); } + if (errno == 0) + __set_errno (save_errno); + if (h->h_addrtype != AF_INET) { /* * Only support INET for now @@ -108,6 +114,7 @@ clnt_create(hostname, prog, vers, proto) /* Enlarge the buffer. */ prtbuflen *= 2; prttmpbuf = __alloca (prtbuflen); + __set_errno (0); } sock = RPC_ANYSOCK; diff --git a/sunrpc/clnt_simp.c b/sunrpc/clnt_simp.c index 2c27388108d..1ec8d0f1266 100644 --- a/sunrpc/clnt_simp.c +++ b/sunrpc/clnt_simp.c @@ -63,6 +63,7 @@ callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) enum clnt_stat clnt_stat; struct hostent hostbuf, *hp; struct timeval timeout, tottimeout; + int save_errno; if (crp == 0) { crp = (struct callrpc_private *)calloc(1, sizeof (*crp)); @@ -96,6 +97,8 @@ callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) buflen = 1024; buffer = __alloca (buflen); + save_errno = errno; + while (__gethostbyname_r (host, &hostbuf, buffer, buflen, &hp, &herr) < 0) if (herr != NETDB_INTERNAL || errno != ERANGE) @@ -105,8 +108,12 @@ callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) /* Enlarge the buffer. */ buflen *= 2; buffer = __alloca (buflen); + __set_errno (0); } + if (errno == 0) + __set_errno (save_errno); + timeout.tv_usec = 0; timeout.tv_sec = 5; bcopy(hp->h_addr, (char *)&server_addr.sin_addr, hp->h_length); diff --git a/sunrpc/getrpcport.c b/sunrpc/getrpcport.c index 3e94dbbf7b6..c405aef6bfb 100644 --- a/sunrpc/getrpcport.c +++ b/sunrpc/getrpcport.c @@ -51,9 +51,12 @@ getrpcport(host, prognum, versnum, proto) size_t buflen; char *buffer; int herr; + int save_errno; buflen = 1024; buffer = __alloca (buflen); + save_errno = errno; + while (__gethostbyname_r (host, &hostbuf, buffer, buflen, &hp, &herr) < 0) if (herr != NETDB_INTERNAL || errno != ERANGE) @@ -63,8 +66,10 @@ getrpcport(host, prognum, versnum, proto) /* Enlarge the buffer. */ buflen *= 2; buffer = __alloca (buflen); + __set_errno (0); } + __set_errno (save_errno); bcopy(hp->h_addr, (char *) &addr.sin_addr, hp->h_length); addr.sin_family = AF_INET; addr.sin_port = 0;