Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 65 additions & 8 deletions libcam/libcam_encoder/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,61 @@
// return ret;
// }

/*
* Ensure output buffer is large enough for the encoded packet.
* Dynamically resizes the buffer if needed (1.5x reserved space, capped at
* max(width*height/2, 2MB)). Drops the frame if it exceeds the reasonable
* upper limit or if realloc fails.
*
* Returns: 1 if data was successfully copied to outbuf,
* 0 if frame was dropped (caller must continue to next iteration).
*/
static int resize_outbuf_if_needed(encoder_video_context_t *enc_video_ctx,

Check warning on line 1593 in libcam/libcam_encoder/encoder.c

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'resize_outbuf_if_needed' is never used.

Check warning on line 1593 in libcam/libcam_encoder/encoder.c

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'resize_outbuf_if_needed' is never used.
encoder_context_t *encoder_ctx,

Check warning on line 1594 in libcam/libcam_encoder/encoder.c

View workflow job for this annotation

GitHub Actions / cppcheck

Parameter 'encoder_ctx' can be declared as pointer to const

Check warning on line 1594 in libcam/libcam_encoder/encoder.c

View workflow job for this annotation

GitHub Actions / static-check / static-check

Parameter 'encoder_ctx' can be declared as pointer to const
AVPacket *pkt)

Check warning on line 1595 in libcam/libcam_encoder/encoder.c

View workflow job for this annotation

GitHub Actions / cppcheck

Parameter 'pkt' can be declared as pointer to const

Check warning on line 1595 in libcam/libcam_encoder/encoder.c

View workflow job for this annotation

GitHub Actions / static-check / static-check

Parameter 'pkt' can be declared as pointer to const
{
/* Guard against invalid negative pkt->size to prevent memcpy overflow,
* since negative int is implicitly converted to a huge size_t value. */
if (pkt->size < 0) {
fprintf(stderr, "ENCODER: invalid packet size %d, dropping frame\n", pkt->size);
return 0;
}

if (pkt->size <= enc_video_ctx->outbuf_size) {
memcpy(enc_video_ctx->outbuf, pkt->data, pkt->size);
return 1;
}

/* Buffer limit: width * height / 2, with 2MB minimum protection */
Comment on lines +1593 to +1609
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): Avoid potential integer overflow in max_reasonable_size computation and size handling.

encoder_ctx->video_width * encoder_ctx->video_height / 2 and alloc_size are both int. For large resolutions this multiplication can overflow before the division, so max_reasonable_size (and later alloc_size) may be derived from a corrupted value. Please compute this in a wider type (e.g. int64_t or size_t), clamp to a sane maximum, then cast down if needed.

int max_reasonable_size = encoder_ctx->video_width * encoder_ctx->video_height / 2;
if (max_reasonable_size < 2 * 1024 * 1024)
max_reasonable_size = 2 * 1024 * 1024;

if (pkt->size > max_reasonable_size) {
fprintf(stderr, "ENCODER: packet size %d exceeds reasonable limit (%d), dropping frame\n",
pkt->size, max_reasonable_size);
return 0;
}

/* Reserve extra space (1.5x) to avoid frequent reallocations */
int alloc_size = pkt->size + (pkt->size >> 1);
if (alloc_size > max_reasonable_size)
alloc_size = max_reasonable_size;

fprintf(stderr, "ENCODER: resizing output buffer (%i -> %i, reserved %i)\n",
enc_video_ctx->outbuf_size, pkt->size, alloc_size);
uint8_t *new_buf = realloc(enc_video_ctx->outbuf, alloc_size);
if (new_buf) {
enc_video_ctx->outbuf = new_buf;
enc_video_ctx->outbuf_size = alloc_size;
memcpy(enc_video_ctx->outbuf, pkt->data, pkt->size);
return 1;
}

fprintf(stderr, "ENCODER: failed to allocate %d bytes, dropping frame\n", alloc_size);
return 0;
}

/*
* encode video frame
* args:
Expand Down Expand Up @@ -1702,10 +1757,11 @@
enc_video_ctx->flags = pkt->flags;
enc_video_ctx->duration = pkt->duration;

if (pkt->size <= enc_video_ctx->outbuf_size)
memcpy(enc_video_ctx->outbuf, pkt->data, pkt->size);
else
fprintf(stderr, "video packet size is bigger than output buffer(%i>%i)\n", pkt->size, enc_video_ctx->outbuf_size);
if (!resize_outbuf_if_needed(enc_video_ctx, encoder_ctx, pkt)) {
last_video_pts = enc_video_ctx->pts;
getLoadLibsInstance()->m_av_packet_unref(pkt);
continue;
}

/* free any side data since we cannot return it */
if (pkt->side_data_elems > 0) {
Expand Down Expand Up @@ -2682,10 +2738,11 @@
enc_video_ctx->flags = pkt->flags;
enc_video_ctx->duration = pkt->duration;

if (pkt->size <= enc_video_ctx->outbuf_size)
memcpy(enc_video_ctx->outbuf, pkt->data, pkt->size);
else
fprintf(stderr, "video packet size is bigger than output buffer(%i>%i)\n", pkt->size, enc_video_ctx->outbuf_size);
if (!resize_outbuf_if_needed(enc_video_ctx, encoder_ctx, pkt)) {
last_video_pts = enc_video_ctx->pts;
getLoadLibsInstance()->m_av_packet_unref(pkt);
continue;
}

/* free any side data since we cannot return it */
if (pkt->side_data_elems > 0) {
Expand Down
Loading