Skip to content

Commit fc4b611

Browse files
committed
fix: PNG write callback memory corruption
1 parent 910ae10 commit fc4b611

1 file changed

Lines changed: 36 additions & 3 deletions

File tree

wasm/png_decode_static.c

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,13 @@ int png_wasm_encode_buffer(
251251
png_set_IHDR(png, info, width, height, 8, color_type,
252252
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
253253

254+
// Set compression parameters for better stability
255+
png_set_compression_level(png, Z_DEFAULT_COMPRESSION);
256+
png_set_compression_method(png, Z_DEFLATED);
257+
png_set_compression_strategy(png, Z_DEFAULT_STRATEGY);
258+
png_set_compression_window_bits(png, 15);
259+
png_set_compression_mem_level(png, 8);
260+
254261
// Write header
255262
png_write_info(png, info);
256263

@@ -362,20 +369,46 @@ static void png_static_read_callback(png_structp png, png_bytep data, size_t len
362369
static void png_static_write_callback(png_structp png, png_bytep data, size_t length) {
363370
png_write_state_t* state = (png_write_state_t*)png_get_io_ptr(png);
364371

372+
// Validate state and input parameters
373+
if (!state || !data || length == 0) {
374+
png_error(png, "Invalid write callback parameters");
375+
return;
376+
}
377+
378+
// Prevent unreasonably large allocations (> 100MB for safety)
379+
if (length > 100 * 1024 * 1024 || state->size > 100 * 1024 * 1024) {
380+
png_error(png, "PNG output too large - possible corruption");
381+
return;
382+
}
383+
384+
// Check for integer overflow
385+
if (state->size + length < state->size) {
386+
png_error(png, "Size overflow in PNG write callback");
387+
return;
388+
}
389+
365390
// Grow buffer if needed
366391
if (state->size + length > state->capacity) {
367392
size_t new_capacity = (state->capacity == 0) ? 8192 : state->capacity * 2;
368393
while (new_capacity < state->size + length) {
369394
new_capacity *= 2;
395+
// Prevent runaway growth
396+
if (new_capacity > 100 * 1024 * 1024) {
397+
png_error(png, "PNG buffer grew too large - possible corruption");
398+
return;
399+
}
370400
}
371401

372-
state->buffer = (unsigned char*)realloc(state->buffer, new_capacity);
373-
if (!state->buffer) {
374-
png_error(png, "Memory allocation failed");
402+
unsigned char* new_buffer = (unsigned char*)realloc(state->buffer, new_capacity);
403+
if (!new_buffer) {
404+
png_error(png, "Memory allocation failed in PNG write callback");
405+
return;
375406
}
407+
state->buffer = new_buffer;
376408
state->capacity = new_capacity;
377409
}
378410

411+
// Safe memory copy
379412
memcpy(state->buffer + state->size, data, length);
380413
state->size += length;
381414
}

0 commit comments

Comments
 (0)