@@ -227,6 +227,8 @@ static never_inline int32_t raise_error(
227
227
RAISE_ERROR((parser), ZONE_NOT_IMPLEMENTED, __VA_ARGS__)
228
228
#define NOT_PERMITTED (parser , ...) \
229
229
RAISE_ERROR((parser), ZONE_NOT_PERMITTED, __VA_ARGS__)
230
+ #define NOT_A_FILE (parser , ...) \
231
+ RAISE_ERROR((parser), ZONE_NOT_A_FILE, __VA_ARGS__)
230
232
231
233
// semantic errors in zone files are special as a secondary may choose
232
234
// to report, but otherwise ignore them. e.g. a TTL with the MSB set. cases
@@ -243,12 +245,26 @@ static never_inline int32_t raise_error(
243
245
244
246
nonnull_all
245
247
warn_unused_result
246
- static really_inline int32_t refill (parser_t * parser )
248
+ static really_inline int32_t reindex (parser_t * parser );
249
+
250
+ // limit maximum size of buffer to avoid malicious inputs claiming all memory.
251
+ // the maximum size of the buffer is the worst-case size of rdata, or 65535
252
+ // bytes, in presentation format. comma-separated value lists as introduced
253
+ // by RFC 9460 allow for double escaping. a reasonable limit is therefore
254
+ // 65535 (rdata) * 4 (\DDD) * 4 (\DDD) + 64 (sufficiently large enough to
255
+ // cover longest key and ancillary characters) bytes.
256
+ #define MAXIMUM_WINDOW_SIZE (65535u * 4u * 4u + 64u)
257
+
258
+ nonnull_all
259
+ warn_unused_result
260
+ static int32_t refill (parser_t * parser )
247
261
{
248
262
// refill if possible (i.e. not if string or if file is empty)
249
263
if (parser -> file -> end_of_file )
250
264
return 0 ;
251
265
266
+ assert (parser -> file -> handle );
267
+
252
268
// move unread data to start of buffer
253
269
char * data = parser -> file -> buffer .data + parser -> file -> buffer .index ;
254
270
// account for non-terminated character-strings
@@ -270,17 +286,21 @@ static really_inline int32_t refill(parser_t *parser)
270
286
271
287
// allocate extra space if required
272
288
if (parser -> file -> buffer .length == parser -> file -> buffer .size ) {
273
- size_t size = parser -> file -> buffer .size + ZONE_WINDOW_SIZE ;
274
- if (!(data = realloc (data , size + 1 )))
275
- OUT_OF_MEMORY (parser , "Cannot increase buffer size to %zu" , size );
289
+ size_t size = parser -> file -> buffer .size ;
290
+ if (parser -> file -> buffer .size >= MAXIMUM_WINDOW_SIZE )
291
+ SYNTAX_ERROR (parser , "Impossibly large input, exceeds %zu bytes" , size );
292
+ size += ZONE_WINDOW_SIZE ;
293
+ if (!(data = realloc (data , size + 1 + ZONE_PADDING_SIZE )))
294
+ OUT_OF_MEMORY (parser , "Not enough memory to allocate buffer of %zu" , size );
276
295
parser -> file -> buffer .size = size ;
277
296
parser -> file -> buffer .data = data ;
278
297
}
279
298
280
- size_t count = fread (parser -> file -> buffer .data + parser -> file -> buffer .length ,
281
- sizeof (parser -> file -> buffer .data [0 ]),
282
- parser -> file -> buffer .size - parser -> file -> buffer .length ,
283
- parser -> file -> handle );
299
+ size_t count = fread (
300
+ parser -> file -> buffer .data + parser -> file -> buffer .length ,
301
+ sizeof (parser -> file -> buffer .data [0 ]),
302
+ parser -> file -> buffer .size - parser -> file -> buffer .length ,
303
+ parser -> file -> handle );
284
304
285
305
if (!count && ferror (parser -> file -> handle ))
286
306
READ_ERROR (parser , "Cannot refill buffer" );
@@ -292,10 +312,6 @@ static really_inline int32_t refill(parser_t *parser)
292
312
return 0 ;
293
313
}
294
314
295
- nonnull_all
296
- warn_unused_result
297
- static really_inline int32_t reindex (parser_t * parser );
298
-
299
315
// do not invoke directly
300
316
nonnull_all
301
317
warn_unused_result
0 commit comments