From: Ulrich Drepper Date: Fri, 30 Jan 1998 17:20:29 +0000 (+0000) Subject: Correctly handle buffer overflow while reading line with fgets. X-Git-Tag: cvs/before-sparc-2_0_x-branch~247 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=69032e82e9c0c26b104ee4a03a83afb3380aace8;p=thirdparty%2Fglibc.git Correctly handle buffer overflow while reading line with fgets. --- diff --git a/grp/fgetgrent_r.c b/grp/fgetgrent_r.c index 44298c5ba60..1a37e0477c3 100644 --- a/grp/fgetgrent_r.c +++ b/grp/fgetgrent_r.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 @@ -60,12 +60,18 @@ __fgetgrent_r (FILE *stream, struct group *resbuf, char *buffer, size_t buflen, do { + buffer[buflen] = '\xff'; p = fgets (buffer, buflen, stream); - if (p == NULL) + if (p == NULL && feof (stream)) { *result = NULL; return errno; } + if (p == NULL || buffer[buflen] != '\xff') + { + *result = NULL; + return errno = ERANGE; + } /* Skip leading blanks. */ while (isspace (*p)) diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c index 91a19c0b774..693ade575e6 100644 --- a/nis/nss_compat/compat-grp.c +++ b/nis/nss_compat/compat-grp.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. Contributed by Thorsten Kukuk , 1996. @@ -315,17 +315,15 @@ getgrent_next_file (struct group *result, ent_t *ent, do { fgetpos (ent->stream, &pos); + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, ent->stream); - if (p == NULL) + if (p == NULL && feof (ent->stream)) + return NSS_STATUS_NOTFOUND; + if (p == NULL || buffer[buflen - 1] != '\xff') { - if (feof (ent->stream)) - return NSS_STATUS_NOTFOUND; - else - { - fsetpos (ent->stream, &pos); - __set_errno (ERANGE); - return NSS_STATUS_TRYAGAIN; - } + fsetpos (ent->stream, &pos); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; } /* Terminate the line for any case. */ @@ -446,17 +444,15 @@ internal_getgrnam_r (const char *name, struct group *result, ent_t *ent, do { fgetpos (ent->stream, &pos); + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, ent->stream); - if (p == NULL) + if (p == NULL && feof (ent->stream)) + return NSS_STATUS_NOTFOUND; + if (p == NULL || buffer[buflen - 1] != '\xff') { - if (feof (ent->stream)) - return NSS_STATUS_NOTFOUND; - else - { - fsetpos (ent->stream, &pos); - __set_errno (ERANGE); - return NSS_STATUS_TRYAGAIN; - } + fsetpos (ent->stream, &pos); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; } /* Terminate the line for any case. */ @@ -607,17 +603,15 @@ internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent, do { fgetpos (ent->stream, &pos); + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, ent->stream); - if (p == NULL) + if (p == NULL && feof (ent->stream)) + return NSS_STATUS_NOTFOUND; + if (p == NULL || buffer[buflen - 1] != '\xff') { - if (feof (ent->stream)) - return NSS_STATUS_NOTFOUND; - else - { - fsetpos (ent->stream, &pos); - __set_errno (ERANGE); - return NSS_STATUS_TRYAGAIN; - } + fsetpos (ent->stream, &pos); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; } /* Terminate the line for any case. */ diff --git a/nis/nss_compat/compat-pwd.c b/nis/nss_compat/compat-pwd.c index afc35e2cfd2..6b1712e5b77 100644 --- a/nis/nss_compat/compat-pwd.c +++ b/nis/nss_compat/compat-pwd.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. Contributed by Thorsten Kukuk , 1996. @@ -565,17 +565,15 @@ getpwent_next_file (struct passwd *result, ent_t *ent, do { fgetpos (ent->stream, &pos); + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, ent->stream); - if (p == NULL) + if (p == NULL && feof (ent->stream)) + return NSS_STATUS_NOTFOUND; + if (p == NULL || buffer[buflen - 1] != '\xff') { - if (feof (ent->stream)) - return NSS_STATUS_NOTFOUND; - else - { - fsetpos (ent->stream, &pos); - __set_errno (ERANGE); - return NSS_STATUS_TRYAGAIN; - } + fsetpos (ent->stream, &pos); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; } /* Terminate the line for any case. */ @@ -745,17 +743,15 @@ internal_getpwnam_r (const char *name, struct passwd *result, ent_t *ent, do { fgetpos (ent->stream, &pos); + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, ent->stream); - if (p == NULL) + if (p == NULL && feof (ent->stream)) + return NSS_STATUS_NOTFOUND; + if (p == NULL || buffer[buflen - 1] != '\xff') { - if (feof (ent->stream)) - return NSS_STATUS_NOTFOUND; - else - { - fsetpos (ent->stream, &pos); - __set_errno (ERANGE); - return NSS_STATUS_TRYAGAIN; - } + fsetpos (ent->stream, &pos); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; } /* Terminate the line for any case. */ @@ -982,17 +978,15 @@ internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent, do { fgetpos (ent->stream, &pos); + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, ent->stream); - if (p == NULL) + if (p == NULL && feof (ent->stream)) + return NSS_STATUS_NOTFOUND; + if (p == NULL || buffer[buflen - 1] != '\xff') { - if (feof (ent->stream)) - return NSS_STATUS_NOTFOUND; - else - { - fsetpos (ent->stream, &pos); - __set_errno (ERANGE); - return NSS_STATUS_TRYAGAIN; - } + fsetpos (ent->stream, &pos); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; } /* Terminate the line for any case. */ diff --git a/nis/nss_compat/compat-spwd.c b/nis/nss_compat/compat-spwd.c index 76ce8831e75..007305c4248 100644 --- a/nis/nss_compat/compat-spwd.c +++ b/nis/nss_compat/compat-spwd.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. Contributed by Thorsten Kukuk , 1996. @@ -515,9 +515,16 @@ getspent_next_file (struct spwd *result, ent_t *ent, do { fgetpos (ent->stream, &pos); + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, ent->stream); - if (p == NULL) + if (p == NULL && feof (ent->stream)) return NSS_STATUS_NOTFOUND; + if (p == NULL || buffer[buflen - 1] != '\xff') + { + fsetpos (ent->stream, &pos); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } /* Terminate the line for any case. */ buffer[buflen - 1] = '\0'; @@ -690,9 +697,16 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, do { fgetpos (ent->stream, &pos); + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, ent->stream); - if (p == NULL) + if (p == NULL && feof (ent->stream)) return NSS_STATUS_NOTFOUND; + if (p == NULL || buffer[buflen - 1] != '\xff') + { + fsetpos (ent->stream, &pos); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } /* Terminate the line for any case. */ buffer[buflen - 1] = '\0'; diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c index ac6b5fa94a8..b36a8b97157 100644 --- a/nss/nss_files/files-XXX.c +++ b/nss/nss_files/files-XXX.c @@ -1,5 +1,5 @@ /* Common code for file-based databases in nss_files module. - 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 @@ -179,16 +179,16 @@ internal_getent (struct STRUCTURE *result, do { /* Terminate the line so that we can test for overflow. */ - data->linebuffer[linebuflen - 1] = '\0'; + data->linebuffer[linebuflen - 1] = '\xff'; p = fgets (data->linebuffer, linebuflen, stream); - if (p == NULL) + if (p == NULL && feof (stream)) { /* End of file or read error. */ H_ERRNO_SET (HOST_NOT_FOUND); return NSS_STATUS_NOTFOUND; } - else if (data->linebuffer[linebuflen - 1] != '\0') + else if (p == NULL || data->linebuffer[linebuflen - 1] != '\xff') { /* The line is too long. Give the user the opportunity to enlarge the buffer. */ diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c index aca89ed73c2..dda20353173 100644 --- a/nss/nss_files/files-alias.c +++ b/nss/nss_files/files-alias.c @@ -1,5 +1,5 @@ /* Mail alias file parser in nss_files module. - 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. Contributed by Ulrich Drepper , 1996. @@ -150,12 +150,12 @@ get_next_alias (const char *match, struct aliasent *result, /* Read the first line. It must contain the alias name and possibly some alias names. */ - first_unused[room_left - 1] = '\0'; + first_unused[room_left - 1] = '\xff'; line = fgets (first_unused, room_left, stream); - if (line == NULL) + if (line == NULL && feof (stream)) /* Nothing to read. */ break; - else if (first_unused[room_left - 1] != '\0') + else if (line == NULL || first_unused[room_left - 1] != '\xff') { /* The line is too long for our buffer. */ no_more_room: @@ -200,7 +200,8 @@ get_next_alias (const char *match, struct aliasent *result, looking for. If it does not match we simply ignore all lines until the next line containing the start of a new alias is found. */ - ignore = match != NULL && strcmp (result->alias_name, match) != 0; + ignore = (match != NULL + && __strcasecmp (result->alias_name, match) != 0); while (! ignore) { @@ -243,11 +244,12 @@ get_next_alias (const char *match, struct aliasent *result, { while (! feof (listfile)) { - first_unused[room_left - 1] = '\0'; + first_unused[room_left - 1] = '\xff'; line = fgets (first_unused, room_left, listfile); - if (line == NULL) + if (line == NULL && feof (listfile)) break; - if (first_unused[room_left - 1] != '\0') + if (line == NULL + || first_unused[room_left - 1] != '\xff') { free (old_line); goto no_more_room; @@ -343,9 +345,11 @@ get_next_alias (const char *match, struct aliasent *result, /* The just read character is a white space and so can be ignored. */ - first_unused[room_left - 1] = '\0'; + first_unused[room_left - 1] = '\xff'; line = fgets (first_unused, room_left, stream); - if (first_unused[room_left - 1] != '\0') + if (line == NULL && feof (stream)) + break; + if (line == NULL || first_unused[room_left - 1] != '\xff') goto no_more_room; cp = strpbrk (line, "#\n"); if (cp != NULL) diff --git a/pwd/fgetpwent_r.c b/pwd/fgetpwent_r.c index 9bf33976756..7f95a1a40ed 100644 --- a/pwd/fgetpwent_r.c +++ b/pwd/fgetpwent_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1996 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1996, 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 @@ -73,12 +73,18 @@ __fgetpwent_r (FILE *stream, struct passwd *resbuf, char *buffer, do { + buffer[buflen] = '\xff'; p = fgets (buffer, buflen, stream); - if (p == NULL) + if (p == NULL && feof (stream)) { *result = NULL; return errno; } + if (p == NULL || buffer[buflen] != '\xff') + { + *result = NULL; + return errno = ERANGE; + } /* Skip leading blanks. */ while (isspace (*p)) diff --git a/shadow/fgetspent_r.c b/shadow/fgetspent_r.c index 403eecf7610..fc9dedea24f 100644 --- a/shadow/fgetspent_r.c +++ b/shadow/fgetspent_r.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 @@ -40,12 +40,18 @@ __fgetspent_r (FILE *stream, struct spwd *resbuf, char *buffer, size_t buflen, do { + buffer[buflen - 1] = '\xff'; p = fgets (buffer, buflen, stream); - if (p == NULL) + if (p == NULL && feof (stream)) { *result = NULL; return errno; } + if (p == NULL || buffer[buflen] != '\xff') + { + *result = NULL; + return errno = ERANGE; + } /* Skip leading blanks. */ while (isspace (*p))