4949#include <string.h>
5050#include <stdio.h>
5151#include <errno.h>
52+ #include <inttypes.h>
5253#include <pwd.h>
5354#include <paths.h>
5455#if defined(OS_APPLE )
7273 * This parses a standard /etc/passwd-format file one entry at a time.
7374 */
7475#ifndef HAVE_FGETPWENT
76+ static int oscap_parse_passwd_id (const char * field , uintmax_t max_value ,
77+ uintmax_t * parsed_value )
78+ {
79+ char * endptr ;
80+ uintmax_t value ;
81+
82+ errno = 0 ;
83+ value = strtoumax (field , & endptr , 10 );
84+ if (errno != 0 || endptr == field || * endptr != '\0' || value > max_value )
85+ return -1 ;
86+
87+ * parsed_value = value ;
88+ return 0 ;
89+ }
90+
7591static struct passwd * oscap_fgetpwent (FILE * fp )
7692{
7793 static char line [2048 ];
7894 static struct passwd pw ;
79- char * fields [7 ], * p ;
95+ char * fields [7 ], * newline , * line_end , * p ;
96+ uintmax_t parsed_uid , parsed_gid ;
8097 int f ;
8198
8299 while (fgets (line , sizeof (line ), fp ) != NULL ) {
100+ newline = memchr (line , '\n' , sizeof (line ) - 1 );
101+ line_end = memchr (line , '\0' , sizeof (line ));
102+ if (newline != NULL )
103+ * newline = '\0' ;
104+ else if (line_end == & line [sizeof (line ) - 1 ]) {
105+ int ch ;
106+
107+ /* Skip truncated records instead of parsing partial passwd entries. */
108+ while ((ch = fgetc (fp )) != '\n' && ch != EOF )
109+ ;
110+ continue ;
111+ }
112+
83113 if (line [0 ] == '#' || line [0 ] == '\n' )
84114 continue ;
85115 f = 0 ;
@@ -94,14 +124,13 @@ static struct passwd *oscap_fgetpwent(FILE *fp)
94124 }
95125 if (f < 7 )
96126 continue ;
97- /* strip trailing newline from shell field */
98- size_t n = strlen (fields [6 ]);
99- if (n > 0 && fields [6 ][n - 1 ] == '\n' )
100- fields [6 ][n - 1 ] = '\0' ;
127+ if (oscap_parse_passwd_id (fields [2 ], (uintmax_t )(uid_t )- 1 , & parsed_uid ) != 0 ||
128+ oscap_parse_passwd_id (fields [3 ], (uintmax_t )(gid_t )- 1 , & parsed_gid ) != 0 )
129+ continue ;
101130 pw .pw_name = fields [0 ];
102131 pw .pw_passwd = fields [1 ];
103- pw .pw_uid = (uid_t )atoi ( fields [ 2 ]) ;
104- pw .pw_gid = (gid_t )atoi ( fields [ 3 ]) ;
132+ pw .pw_uid = (uid_t )parsed_uid ;
133+ pw .pw_gid = (gid_t )parsed_gid ;
105134 pw .pw_gecos = fields [4 ];
106135 pw .pw_dir = fields [5 ];
107136 pw .pw_shell = fields [6 ];
0 commit comments