Mercurial > hg > nginx
comparison src/core/ngx_parse.c @ 6011:429a8c65f0a7
Core: overflow detection in ngx_parse_time() (ticket #732).
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Tue, 17 Mar 2015 00:26:20 +0300 |
parents | 040e2736e8dc |
children | 4ccb37b04454 |
comparison
equal
deleted
inserted
replaced
6010:040e2736e8dc | 6011:429a8c65f0a7 |
---|---|
101 ngx_int_t | 101 ngx_int_t |
102 ngx_parse_time(ngx_str_t *line, ngx_uint_t is_sec) | 102 ngx_parse_time(ngx_str_t *line, ngx_uint_t is_sec) |
103 { | 103 { |
104 u_char *p, *last; | 104 u_char *p, *last; |
105 ngx_int_t value, total, scale; | 105 ngx_int_t value, total, scale; |
106 ngx_uint_t max, valid; | 106 ngx_int_t max, cutoff, cutlim; |
107 ngx_uint_t valid; | |
107 enum { | 108 enum { |
108 st_start = 0, | 109 st_start = 0, |
109 st_year, | 110 st_year, |
110 st_month, | 111 st_month, |
111 st_week, | 112 st_week, |
118 } step; | 119 } step; |
119 | 120 |
120 valid = 0; | 121 valid = 0; |
121 value = 0; | 122 value = 0; |
122 total = 0; | 123 total = 0; |
124 cutoff = NGX_MAX_INT_T_VALUE / 10; | |
125 cutlim = NGX_MAX_INT_T_VALUE % 10; | |
123 step = is_sec ? st_start : st_month; | 126 step = is_sec ? st_start : st_month; |
124 | 127 |
125 p = line->data; | 128 p = line->data; |
126 last = p + line->len; | 129 last = p + line->len; |
127 | 130 |
128 while (p < last) { | 131 while (p < last) { |
129 | 132 |
130 if (*p >= '0' && *p <= '9') { | 133 if (*p >= '0' && *p <= '9') { |
134 if (value >= cutoff && (value > cutoff || *p - '0' > cutlim)) { | |
135 return NGX_ERROR; | |
136 } | |
137 | |
131 value = value * 10 + (*p++ - '0'); | 138 value = value * 10 + (*p++ - '0'); |
132 valid = 1; | 139 valid = 1; |
133 continue; | 140 continue; |
134 } | 141 } |
135 | 142 |
138 case 'y': | 145 case 'y': |
139 if (step > st_start) { | 146 if (step > st_start) { |
140 return NGX_ERROR; | 147 return NGX_ERROR; |
141 } | 148 } |
142 step = st_year; | 149 step = st_year; |
143 max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 365); | 150 max = NGX_MAX_INT_T_VALUE / (60 * 60 * 24 * 365); |
144 scale = 60 * 60 * 24 * 365; | 151 scale = 60 * 60 * 24 * 365; |
145 break; | 152 break; |
146 | 153 |
147 case 'M': | 154 case 'M': |
148 if (step >= st_month) { | 155 if (step >= st_month) { |
149 return NGX_ERROR; | 156 return NGX_ERROR; |
150 } | 157 } |
151 step = st_month; | 158 step = st_month; |
152 max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 30); | 159 max = NGX_MAX_INT_T_VALUE / (60 * 60 * 24 * 30); |
153 scale = 60 * 60 * 24 * 30; | 160 scale = 60 * 60 * 24 * 30; |
154 break; | 161 break; |
155 | 162 |
156 case 'w': | 163 case 'w': |
157 if (step >= st_week) { | 164 if (step >= st_week) { |
158 return NGX_ERROR; | 165 return NGX_ERROR; |
159 } | 166 } |
160 step = st_week; | 167 step = st_week; |
161 max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 7); | 168 max = NGX_MAX_INT_T_VALUE / (60 * 60 * 24 * 7); |
162 scale = 60 * 60 * 24 * 7; | 169 scale = 60 * 60 * 24 * 7; |
163 break; | 170 break; |
164 | 171 |
165 case 'd': | 172 case 'd': |
166 if (step >= st_day) { | 173 if (step >= st_day) { |
167 return NGX_ERROR; | 174 return NGX_ERROR; |
168 } | 175 } |
169 step = st_day; | 176 step = st_day; |
170 max = NGX_MAX_INT32_VALUE / (60 * 60 * 24); | 177 max = NGX_MAX_INT_T_VALUE / (60 * 60 * 24); |
171 scale = 60 * 60 * 24; | 178 scale = 60 * 60 * 24; |
172 break; | 179 break; |
173 | 180 |
174 case 'h': | 181 case 'h': |
175 if (step >= st_hour) { | 182 if (step >= st_hour) { |
176 return NGX_ERROR; | 183 return NGX_ERROR; |
177 } | 184 } |
178 step = st_hour; | 185 step = st_hour; |
179 max = NGX_MAX_INT32_VALUE / (60 * 60); | 186 max = NGX_MAX_INT_T_VALUE / (60 * 60); |
180 scale = 60 * 60; | 187 scale = 60 * 60; |
181 break; | 188 break; |
182 | 189 |
183 case 'm': | 190 case 'm': |
184 if (*p == 's') { | 191 if (*p == 's') { |
185 if (is_sec || step >= st_msec) { | 192 if (is_sec || step >= st_msec) { |
186 return NGX_ERROR; | 193 return NGX_ERROR; |
187 } | 194 } |
188 p++; | 195 p++; |
189 step = st_msec; | 196 step = st_msec; |
190 max = NGX_MAX_INT32_VALUE; | 197 max = NGX_MAX_INT_T_VALUE; |
191 scale = 1; | 198 scale = 1; |
192 break; | 199 break; |
193 } | 200 } |
194 | 201 |
195 if (step >= st_min) { | 202 if (step >= st_min) { |
196 return NGX_ERROR; | 203 return NGX_ERROR; |
197 } | 204 } |
198 step = st_min; | 205 step = st_min; |
199 max = NGX_MAX_INT32_VALUE / 60; | 206 max = NGX_MAX_INT_T_VALUE / 60; |
200 scale = 60; | 207 scale = 60; |
201 break; | 208 break; |
202 | 209 |
203 case 's': | 210 case 's': |
204 if (step >= st_sec) { | 211 if (step >= st_sec) { |
205 return NGX_ERROR; | 212 return NGX_ERROR; |
206 } | 213 } |
207 step = st_sec; | 214 step = st_sec; |
208 max = NGX_MAX_INT32_VALUE; | 215 max = NGX_MAX_INT_T_VALUE; |
209 scale = 1; | 216 scale = 1; |
210 break; | 217 break; |
211 | 218 |
212 case ' ': | 219 case ' ': |
213 if (step >= st_sec) { | 220 if (step >= st_sec) { |
214 return NGX_ERROR; | 221 return NGX_ERROR; |
215 } | 222 } |
216 step = st_last; | 223 step = st_last; |
217 max = NGX_MAX_INT32_VALUE; | 224 max = NGX_MAX_INT_T_VALUE; |
218 scale = 1; | 225 scale = 1; |
219 break; | 226 break; |
220 | 227 |
221 default: | 228 default: |
222 return NGX_ERROR; | 229 return NGX_ERROR; |
225 if (step != st_msec && !is_sec) { | 232 if (step != st_msec && !is_sec) { |
226 scale *= 1000; | 233 scale *= 1000; |
227 max /= 1000; | 234 max /= 1000; |
228 } | 235 } |
229 | 236 |
230 if ((ngx_uint_t) value > max) { | 237 if (value > max) { |
231 return NGX_ERROR; | 238 return NGX_ERROR; |
232 } | 239 } |
233 | 240 |
234 total += value * scale; | 241 value *= scale; |
235 | 242 |
236 if ((ngx_uint_t) total > NGX_MAX_INT32_VALUE) { | 243 if (total > NGX_MAX_INT_T_VALUE - value) { |
237 return NGX_ERROR; | 244 return NGX_ERROR; |
238 } | 245 } |
246 | |
247 total += value; | |
239 | 248 |
240 value = 0; | 249 value = 0; |
241 | 250 |
242 while (p < last && *p == ' ') { | 251 while (p < last && *p == ' ') { |
243 p++; | 252 p++; |
244 } | 253 } |
245 } | 254 } |
246 | 255 |
247 if (valid) { | 256 if (!valid) { |
248 return total + value * (is_sec ? 1 : 1000); | 257 return NGX_ERROR; |
249 } | 258 } |
250 | 259 |
251 return NGX_ERROR; | 260 if (!is_sec) { |
261 if (value > NGX_MAX_INT_T_VALUE / 1000) { | |
262 return NGX_ERROR; | |
263 } | |
264 | |
265 value *= 1000; | |
266 } | |
267 | |
268 if (total > NGX_MAX_INT_T_VALUE - value) { | |
269 return NGX_ERROR; | |
270 } | |
271 | |
272 return total + value; | |
252 } | 273 } |