1
1
/*
2
2
* SPDX-License-Identifier: ISC
3
3
*
4
- * Copyright (c) 2013-2016 Todd C. Miller <Todd.Miller@sudo.ws>
4
+ * Copyright (c) 2013-2019 Todd C. Miller <Todd.Miller@sudo.ws>
5
5
*
6
6
* Permission to use, copy, modify, and distribute this software for any
7
7
* purpose with or without fee is hereby granted, provided that the above
48
48
#include "sudo_debug.h"
49
49
#include "sudo_util.h"
50
50
51
+ /*
52
+ * Make sure that the ID ends with a valid separator char.
53
+ */
54
+ static bool
55
+ valid_separator (const char * p , const char * ep , const char * sep )
56
+ {
57
+ bool valid = false;
58
+ debug_decl (valid_separator , SUDO_DEBUG_UTIL )
59
+
60
+ if (ep != p ) {
61
+ /* check for valid separator (including '\0') */
62
+ if (sep == NULL )
63
+ sep = "" ;
64
+ do {
65
+ if (* ep == * sep )
66
+ valid = true;
67
+ } while (* sep ++ != '\0' );
68
+ }
69
+ debug_return_bool (valid );
70
+ }
71
+
51
72
/*
52
73
* Parse a uid/gid in string form.
53
74
* If sep is non-NULL, it contains valid separator characters (e.g. comma, space)
@@ -62,36 +83,33 @@ sudo_strtoid_v1(const char *p, const char *sep, char **endp, const char **errstr
62
83
char * ep ;
63
84
id_t ret = 0 ;
64
85
long long llval ;
65
- bool valid = false;
66
86
debug_decl (sudo_strtoid , SUDO_DEBUG_UTIL )
67
87
68
88
/* skip leading space so we can pick up the sign, if any */
69
89
while (isspace ((unsigned char )* p ))
70
90
p ++ ;
71
- if ( sep == NULL )
72
- sep = "" ;
91
+
92
+ /* While id_t may be 64-bit signed, uid_t and gid_t are 32-bit unsigned. */
73
93
errno = 0 ;
74
94
llval = strtoll (p , & ep , 10 );
75
- if (ep != p ) {
76
- /* check for valid separator (including '\0') */
77
- do {
78
- if (* ep == * sep )
79
- valid = true;
80
- } while (* sep ++ != '\0' );
95
+ if ((errno == ERANGE && llval == LLONG_MAX ) || llval > (id_t )UINT_MAX ) {
96
+ errno = ERANGE ;
97
+ if (errstr != NULL )
98
+ * errstr = N_ ("value too large" );
99
+ goto done ;
81
100
}
82
- if (!valid ) {
101
+ if ((errno == ERANGE && llval == LLONG_MIN ) || llval < INT_MIN ) {
102
+ errno = ERANGE ;
83
103
if (errstr != NULL )
84
- * errstr = N_ ("invalid value" );
85
- errno = EINVAL ;
104
+ * errstr = N_ ("value too small" );
86
105
goto done ;
87
106
}
88
- if (errno == ERANGE ) {
89
- if (errstr != NULL ) {
90
- if (llval == LLONG_MAX )
91
- * errstr = N_ ("value too large" );
92
- else
93
- * errstr = N_ ("value too small" );
94
- }
107
+
108
+ /* Disallow id -1, which means "no change". */
109
+ if (!valid_separator (p , ep , sep ) || llval == -1 || llval == (id_t )UINT_MAX ) {
110
+ if (errstr != NULL )
111
+ * errstr = N_ ("invalid value" );
112
+ errno = EINVAL ;
95
113
goto done ;
96
114
}
97
115
ret = (id_t )llval ;
@@ -108,30 +126,15 @@ sudo_strtoid_v1(const char *p, const char *sep, char **endp, const char **errstr
108
126
{
109
127
char * ep ;
110
128
id_t ret = 0 ;
111
- bool valid = false;
112
129
debug_decl (sudo_strtoid , SUDO_DEBUG_UTIL )
113
130
114
131
/* skip leading space so we can pick up the sign, if any */
115
132
while (isspace ((unsigned char )* p ))
116
133
p ++ ;
117
- if (sep == NULL )
118
- sep = "" ;
134
+
119
135
errno = 0 ;
120
136
if (* p == '-' ) {
121
137
long lval = strtol (p , & ep , 10 );
122
- if (ep != p ) {
123
- /* check for valid separator (including '\0') */
124
- do {
125
- if (* ep == * sep )
126
- valid = true;
127
- } while (* sep ++ != '\0' );
128
- }
129
- if (!valid ) {
130
- if (errstr != NULL )
131
- * errstr = N_ ("invalid value" );
132
- errno = EINVAL ;
133
- goto done ;
134
- }
135
138
if ((errno == ERANGE && lval == LONG_MAX ) || lval > INT_MAX ) {
136
139
errno = ERANGE ;
137
140
if (errstr != NULL )
@@ -144,28 +147,31 @@ sudo_strtoid_v1(const char *p, const char *sep, char **endp, const char **errstr
144
147
* errstr = N_ ("value too small" );
145
148
goto done ;
146
149
}
147
- ret = (id_t )lval ;
148
- } else {
149
- unsigned long ulval = strtoul (p , & ep , 10 );
150
- if (ep != p ) {
151
- /* check for valid separator (including '\0') */
152
- do {
153
- if (* ep == * sep )
154
- valid = true;
155
- } while (* sep ++ != '\0' );
156
- }
157
- if (!valid ) {
150
+
151
+ /* Disallow id -1, which means "no change". */
152
+ if (!valid_separator (p , ep , sep ) || lval == -1 ) {
158
153
if (errstr != NULL )
159
154
* errstr = N_ ("invalid value" );
160
155
errno = EINVAL ;
161
156
goto done ;
162
157
}
158
+ ret = (id_t )lval ;
159
+ } else {
160
+ unsigned long ulval = strtoul (p , & ep , 10 );
163
161
if ((errno == ERANGE && ulval == ULONG_MAX ) || ulval > UINT_MAX ) {
164
162
errno = ERANGE ;
165
163
if (errstr != NULL )
166
164
* errstr = N_ ("value too large" );
167
165
goto done ;
168
166
}
167
+
168
+ /* Disallow id -1, which means "no change". */
169
+ if (!valid_separator (p , ep , sep ) || ulval == UINT_MAX ) {
170
+ if (errstr != NULL )
171
+ * errstr = N_ ("invalid value" );
172
+ errno = EINVAL ;
173
+ goto done ;
174
+ }
169
175
ret = (id_t )ulval ;
170
176
}
171
177
if (errstr != NULL )
0 commit comments