|
176 | 176 | auto tail = find!(c => c == ' ')(str);
|
177 | 177 | size_t len = str.length - tail.length;
|
178 | 178 |
|
| 179 | + import core.checkedint : mulu; |
| 180 | + |
| 181 | + bool overflowed; |
| 182 | + |
179 | 183 | for (; i < len; i++)
|
180 | 184 | {
|
181 | 185 | char c = str[i];
|
|
188 | 192 | {
|
189 | 193 | switch (c)
|
190 | 194 | {
|
| 195 | + |
191 | 196 | case 'G':
|
192 |
| - v <<= 30; |
| 197 | + v = mulu(v, 1024 * 1024 * 1024, overflowed); |
193 | 198 | break;
|
194 | 199 |
|
195 | 200 | case 'M':
|
196 |
| - v <<= 20; |
| 201 | + v = mulu(v, 1024 * 1024, overflowed); |
197 | 202 | break;
|
198 | 203 |
|
199 | 204 | case 'K':
|
200 |
| - v <<= 10; |
| 205 | + v = mulu(v, 1024, overflowed); |
201 | 206 | break;
|
202 | 207 |
|
203 | 208 | case 'B':
|
|
207 | 212 | return parseError("value with unit type M, K or B", optname, str, "with suffix");
|
208 | 213 | }
|
209 | 214 |
|
| 215 | + if (overflowed) |
| 216 | + return overflowedError(optname, str); |
| 217 | + |
210 | 218 | i++;
|
211 | 219 | break;
|
212 | 220 | }
|
|
222 | 230 | return parseError("a number", optname, str, errName);
|
223 | 231 |
|
224 | 232 | if (mayHaveSuffix && isdigit(str[len-1]))
|
225 |
| - v <<= 20; // No suffix found, default to megabytes |
| 233 | + { |
| 234 | + // No suffix found, default to megabytes |
| 235 | + |
| 236 | + v = mulu(v, 1024 * 1024, overflowed); |
| 237 | + |
| 238 | + if (overflowed) |
| 239 | + return overflowedError(optname, str); |
| 240 | + } |
226 | 241 |
|
227 | 242 | if (v > res.max)
|
228 | 243 | return parseError("a number " ~ T.max.stringof ~ " or below", optname, str[0 .. i], errName);
|
@@ -310,6 +325,16 @@ bool parseError(const scope char[] exp, const scope char[] opt, const scope char
|
310 | 325 | return false;
|
311 | 326 | }
|
312 | 327 |
|
| 328 | +bool overflowedError(const scope char[] opt, const scope char[] got) |
| 329 | +{ |
| 330 | + version (CoreUnittest) if (inUnittest) return false; |
| 331 | + |
| 332 | + fprintf(stderr, "Argument for %.*s option '%.*s' is too big.\n", |
| 333 | + cast(int)opt.length, opt.ptr, |
| 334 | + cast(int)got.length, got.ptr); |
| 335 | + return false; |
| 336 | +} |
| 337 | + |
313 | 338 | size_t min(size_t a, size_t b) { return a <= b ? a : b; }
|
314 | 339 |
|
315 | 340 | version (CoreUnittest) __gshared bool inUnittest;
|
@@ -369,6 +394,8 @@ unittest
|
369 | 394 | assert(conf.disable);
|
370 | 395 | assert(conf.minPoolSize == 1024UL * 1024 * 1024 * 3);
|
371 | 396 |
|
| 397 | + assert(!conf.parseOptions("minPoolSize:922337203685477G"), "size_t overflow"); |
| 398 | + |
372 | 399 | assert(conf.parseOptions("heapSizeFactor:3.1"));
|
373 | 400 | assert(conf.heapSizeFactor == 3.1f);
|
374 | 401 | assert(conf.parseOptions("heapSizeFactor:3.1234567890 disable:0"));
|
|
0 commit comments