Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
21611f6
protection patch
kpchoi Jul 6, 2026
9cba885
fixed memory leak
kpchoi Jul 7, 2026
4ff5f57
Validate tile QP range when parsing tile header
kpchoi Jul 7, 2026
a995224
Cast to unsigned char before toupper() in check_file_name_type
kpchoi Jul 7, 2026
1813adf
Bound AC coefficient run length to remaining block capacity
kpchoi Jul 7, 2026
832ee20
Make thread-pool sync object deletion NULL-safe
kpchoi Jul 7, 2026
54edcf7
Free payload buffer when metadata group limit is reached
kpchoi Jul 7, 2026
4235d99
Reject unsupported bit depths in image copy
kpchoi Jul 7, 2026
9f49242
Bound --config count in argument parsing
kpchoi Jul 8, 2026
3cd1f67
Reject NULL image buffer in frame prepare
kpchoi Jul 8, 2026
9d7136f
Bound Y4M frame dimensions
kpchoi Jul 8, 2026
a5cce73
Bound encoder frame dimensions
kpchoi Jul 8, 2026
8d90ba8
Fix heap buffer overflow in libopenapv encoder (#212)
fkyslov Jul 8, 2026
6672f01
Reject invalid Y4M frame rate
kpchoi Jul 8, 2026
42a228b
Use ERR: prefix consistently in log messages
kpchoi Jul 8, 2026
de60bba
Avoid overflow in PSNR calculation
kpchoi Jul 8, 2026
bd2bc31
Clip RDO coefficient candidate to s16 range
kpchoi Jul 8, 2026
adaeeae
Widen tile cost accumulator to avoid overflow
kpchoi Jul 8, 2026
235d8b5
Clean up only initialized thread objects on error
kpchoi Jul 8, 2026
25e881a
Validate bitrate and fps parameter strings
kpchoi Jul 8, 2026
bbd3ed3
Discard non-finite rate-control updates
kpchoi Jul 8, 2026
49a2ae3
Bound tile size to picture dimensions
kpchoi Jul 8, 2026
495b446
Validate frame dimensions right after parsing
kpchoi Jul 8, 2026
6e59b61
Sanitize lambda before QP conversion in rate control
kpchoi Jul 8, 2026
4129be3
Validate caller buffer allocation before padding
kpchoi Jul 9, 2026
4ee2dd9
Add imgb validation and return error from md5 helper
kpchoi Jul 9, 2026
514bb9e
Rename imgb validator to oapv_imgb_is_valid
kpchoi Jul 9, 2026
d8aaf2a
Validate image buffers before copy
kpchoi Jul 9, 2026
6796e80
Bound VLC bitstream reads against buffer end
kpchoi Jul 9, 2026
257ce7a
Guard against failed image buffer allocation in app
kpchoi Jul 9, 2026
42c5fd8
Initialize and validate Y4M header parameters
kpchoi Jul 10, 2026
e242172
Fix bitstream read shift overflow and set decoder bitb size
kpchoi Jul 10, 2026
fae622b
Reject decoder stream size larger than buffer size
kpchoi Jul 10, 2026
611f146
Bound tile-size read and reject undersized PBU
kpchoi Jul 10, 2026
85dba81
Reject NULL decode arguments
kpchoi Jul 10, 2026
bf429c7
Validate reconstruction buffer size
kpchoi Jul 10, 2026
f0290f1
Reject output buffer too small for frame header
kpchoi Jul 10, 2026
a337630
Reject out-of-range frame dimensions in param update
kpchoi Jul 10, 2026
841a7e6
Bound exp-golomb k in 1-bit VLC read
kpchoi Jul 10, 2026
cb518ce
Validate param parse inputs and guard fps divisor
kpchoi Jul 10, 2026
c17a4b3
Require frame rate only when used and add fps error code
kpchoi Jul 10, 2026
a0d268b
Guard metadata write against full output buffer
kpchoi Jul 10, 2026
79dc40d
Use INVALID_FPS consistently for frame-rate errors
kpchoi Jul 10, 2026
f13eba8
Prevent leftbits underflow on truncated bitstream
kpchoi Jul 10, 2026
0270b13
Bound frame count and null-check metadata payload APIs
kpchoi Jul 10, 2026
b3c9d94
Bound rate-table indices in bitrate/level lookup
kpchoi Jul 10, 2026
cf20bb5
Avoid overflow in key bitrate resolution lookup
kpchoi Jul 10, 2026
d05f5eb
Validate create/config/metadata inputs and add band error code
kpchoi Jul 11, 2026
83d07ab
Use reconstruction stride when writing recon picture
kpchoi Jul 11, 2026
b240128
Join encoder worker threads before handling errors
kpchoi Jul 11, 2026
0b81512
Reject bitrate strings that overflow int
kpchoi Jul 11, 2026
6e553ff
Null-check and bound metadata lookup APIs
kpchoi Jul 11, 2026
9772d51
Widen luma sample rate to avoid int overflow
kpchoi Jul 11, 2026
df4343e
Add frame index to encoder config and null-check entry points
kpchoi Jul 13, 2026
866900a
Clamp itrans step and guard thread-pool allocation
kpchoi Jul 13, 2026
5363fa0
Join rate-control worker threads before handling errors
kpchoi Jul 13, 2026
52c0269
Clamp tile size to picture instead of rejecting
kpchoi Jul 13, 2026
1126c4e
Bump minor version for new API additions
kpchoi Jul 13, 2026
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
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ option(OAPV_BUILD_SHARED_LIB "Build oapv shared library" ON)

option(ENABLE_COVERAGE "Enable code coverage measurement" OFF)

option(OAPV_ENABLE_SANITIZERS "Enable AddressSanitizer and UndefinedBehaviorSanitizer" OFF)

if(OAPV_BUILD_APPS AND OAPV_APP_STATIC_BUILD AND NOT OAPV_BUILD_STATIC_LIB)
message(FATAL_ERROR "Cannot build static apps without static lib.")
endif()
Expand Down Expand Up @@ -130,6 +132,12 @@ elseif(UNIX OR MINGW)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
endif()

if(OAPV_ENABLE_SANITIZERS)
# -fno-omit-frame-pointer overrides the earlier -fomit-frame-pointer
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined")
endif()
else()
message("Unknown compiler")
endif()
Expand Down
1 change: 1 addition & 0 deletions app/oapv_app_args.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ static int args_parse(args_parser_t *args, int argc, const char *argv[],
for(i = 1; i < argc; i++) {
if(!strcmp(argv[i], "--" ARGS_KEY_LONG_CONFIG)) {
if(i + 1 < argc) {
if(num_configs >= ARGS_MAX_NUM_CONF_FILES) break;
num_configs++;
pos_conf_files[num_configs - 1] = i + 1;
}
Expand Down
26 changes: 15 additions & 11 deletions app/oapv_app_dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
#include "oapv_app_args.h"
#include "oapv_app_y4m.h"

#define MAX_BS_BUF 128 * 1024 * 1024 /* byte */
#define MAX_NUM_METADATA_PLDS 128 /* max number of metadata payloads per access unit */
#define MAX_BS_BUF 128 * 1024 * 1024 /* byte */

// check generic frame or not
#define IS_NON_AUX_FRM(frm) (((frm)->pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME) || ((frm)->pbu_type == OAPV_PBU_TYPE_NON_PRIMARY_FRAME))
Expand Down Expand Up @@ -238,7 +237,7 @@ static int read_bitstream(FILE *fp, unsigned char *bs_buf, int *bs_buf_size)
return 0;
}
else if(ret < 0) {
logerr("Cannot read bitstream size!\n");
logerr("ERR: Cannot read bitstream size!\n");
return -1;
}
if(au_size > 0) {
Expand All @@ -250,7 +249,7 @@ static int read_bitstream(FILE *fp, unsigned char *bs_buf, int *bs_buf_size)
while(au_size > 0) {
/* read byte */
if(1 != fread(&b, 1, 1, fp)) {
logerr("Cannot read bitstream!\n");
logerr("ERR: Cannot read bitstream!\n");
return -1;
}
bs_buf[read_size] = b;
Expand All @@ -261,12 +260,12 @@ static int read_bitstream(FILE *fp, unsigned char *bs_buf, int *bs_buf_size)
}
else {
/* size field present but zero: malformed bitstream */
logerr("Cannot read bitstream size!\n");
logerr("ERR: Cannot read bitstream size!\n");
return -1;
}
}
else {
logerr("Cannot seek bitstream!\n");
logerr("ERR: Cannot seek bitstream!\n");
return -1;
}
return read_size + 4;
Expand All @@ -281,7 +280,7 @@ static int set_extra_config(oapvd_t id, args_var_t *args_vars)
size = 4;
ret = oapvd_config(id, OAPV_CFG_SET_USE_FRM_HASH, &value, &size);
if(OAPV_FAILED(ret)) {
logerr("failed to set config for using frame hash\n");
logerr("ERR: failed to set config for using frame hash\n");
return -1;
}
}
Expand All @@ -290,7 +289,7 @@ static int set_extra_config(oapvd_t id, args_var_t *args_vars)
size = 4;
ret = oapvd_config(id, OAPV_CFG_SET_DISABLE_COMPANDING, &value, &size);
if(OAPV_FAILED(ret)) {
logerr("failed to set config for disabling companding process\n");
logerr("ERR: failed to set config for disabling companding process\n");
return -1;
}
}
Expand Down Expand Up @@ -565,6 +564,7 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m)

/* main decoding block */
bitb.addr = bs_buf;
bitb.bsize = MAX_BS_BUF;
bitb.ssize = bs_buf_size;
memset(&stat, 0, sizeof(oapvd_stat_t));

Expand Down Expand Up @@ -599,8 +599,8 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m)
}

/* validate number of metadata payloads */
if(num_plds < 0 || num_plds > MAX_NUM_METADATA_PLDS) {
logerr("ERR: invalid number of metadata payloads (%d), valid range is 0-%d\n", num_plds, MAX_NUM_METADATA_PLDS);
if(num_plds < 0 || num_plds > OAPV_MAX_NUM_META_PAYLOADS) {
logerr("ERR: invalid number of metadata payloads (%d), valid range is 0-%d\n", num_plds, OAPV_MAX_NUM_META_PAYLOADS);
goto END;
}

Expand Down Expand Up @@ -706,6 +706,9 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m)
if(imgb_w != NULL)
imgb_w->release(imgb_w);

if(bs_buf != NULL)
free(bs_buf);

return 0;
}

Expand Down Expand Up @@ -740,7 +743,7 @@ static int read_u32(FILE *fp, unsigned int * val)
static int read_pbu(FILE *fp, unsigned char *pbu, unsigned int pbu_size)
{
if(pbu_size != fread(pbu, 1, pbu_size, fp)) {
logerr("Cannot read PDU!\n");
logerr("ERR: Cannot read PDU!\n");
return -1;
}
return 0;
Expand Down Expand Up @@ -951,6 +954,7 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m)

// start to decode a frame
bitb.addr = pbu;
bitb.bsize = pbu_size;
bitb.ssize = pbu_size;

clk_beg = oapv_clk_get();
Expand Down
17 changes: 13 additions & 4 deletions app/oapv_app_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ typedef struct args_var {

char width[16];
char height[16];
char fps[16];
char fps[24];

char qp[16];
char qp_offset_c1[16];
Expand Down Expand Up @@ -520,7 +520,7 @@ static int set_extra_config(oapve_t id, args_var_t *vars, oapve_param_t *param)
if(vars->hash) {
value = 1;
size = 4;
ret = oapve_config(id, OAPV_CFG_SET_USE_FRM_HASH, &value, &size);
ret = oapve_config(id, OAPV_CFG_FRM(OAPV_CFG_SET_USE_FRM_HASH, 0), &value, &size);
if(OAPV_FAILED(ret)) {
logerr("ERR: failed to set config for using frame hash\n");
return -1;
Expand Down Expand Up @@ -706,7 +706,7 @@ static int family_to_bitrate(char * family, oapve_param_t *param)
#define UPDATE_A_PARAM_W_KEY_VAL(param, key, val) \
if(strlen(val) > 0) { \
if(OAPV_FAILED(oapve_param_parse(param, key, val))) { \
logerr("input value (%s) of %s is invalid\n", val, key); \
logerr("ERR: input value (%s) of %s is invalid\n", val, key); \
return -1; \
} \
}
Expand All @@ -719,6 +719,11 @@ static int update_param(args_var_t *vars, oapve_param_t *param)

UPDATE_A_PARAM_W_KEY_VAL(param, "width", vars->width);
UPDATE_A_PARAM_W_KEY_VAL(param, "height", vars->height);
if(param->w <= 0 || param->w > IMGB_MAX_W || param->h <= 0 || param->h > IMGB_MAX_H) {
logerr("ERR: frame dimensions %dx%d out of range (max %dx%d)\n",
param->w, param->h, IMGB_MAX_W, IMGB_MAX_H);
return -1;
}
UPDATE_A_PARAM_W_KEY_VAL(param, "fps", vars->fps);

UPDATE_A_PARAM_W_KEY_VAL(param, "qp", vars->qp);
Expand Down Expand Up @@ -782,7 +787,7 @@ static int parse_master_display(const char* data_string, oapvm_payload_mdcv_t *m
// Check if sscanf successfully assigned all expected fields (10 numerical values).
const int expected_fields = 10;
if (assigned_fields != expected_fields) {
logerr("Parsing error: master display color volume information");
logerr("ERR: Parsing error: master display color volume information");
return -1;
}
return 0; // Success
Expand Down Expand Up @@ -1127,9 +1132,11 @@ int main(int argc, const char **argv)
}
else {
imgb_r = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, args_var->input_depth, 0));
if(imgb_r == NULL) { ret = -1; goto ERR; }
ifrms.frm[i].imgb = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, codec_depth, 0));
}
}
if(ifrms.frm[i].imgb == NULL) { ret = -1; goto ERR; }

if(is_rec) {
if(args_var->input_depth == codec_depth) {
Expand All @@ -1142,9 +1149,11 @@ int main(int argc, const char **argv)
else
{
imgb_w = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, args_var->input_depth, 0));
if(imgb_w == NULL) { ret = -1; goto ERR; }
rfrms.frm[i].imgb = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, codec_depth, 0));
}
}
if(rfrms.frm[i].imgb == NULL) { ret = -1; goto ERR; }
rfrms.num_frms++;
}
ifrms.num_frms++;
Expand Down
69 changes: 56 additions & 13 deletions app/oapv_app_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ oapv_imgb_t *imgb_create(int w, int h, int cs)

/* reject invalid or out-of-range resolution */
if(w <= 0 || h <= 0 || w > IMGB_MAX_W || h > IMGB_MAX_H || bd <= 0) {
logerr("invalid image parameter (w=%d, h=%d, byte-depth=%d)\n", w, h, bd);
logerr("ERR: invalid image parameter (w=%d, h=%d, byte-depth=%d)\n", w, h, bd);
goto ERR;
}

Expand Down Expand Up @@ -385,7 +385,7 @@ oapv_imgb_t *imgb_create(int w, int h, int cs)
return imgb;

ERR:
logerr("cannot create image buffer\n");
logerr("ERR: cannot create image buffer\n");
if(imgb) {
for(int i = 0; i < OAPV_MAX_CC; i++) {
if(imgb->a[i])
Expand All @@ -407,11 +407,11 @@ static int imgb_read(FILE *fp, oapv_imgb_t *img, int width, int height, int is_y
if(6 != fread(t_buf, 1, 6, fp))
return -1;
if(memcmp(t_buf, "FRAME", 5)) {
logerr("Loss of framing in Y4M input data\n");
logerr("ERR: Loss of framing in Y4M input data\n");
return -1;
}
if(t_buf[5] != '\n') {
logerr("Error parsing Y4M frame header\n");
logerr("ERR: parsing Y4M frame header\n");
return -1;
}
}
Expand All @@ -431,7 +431,7 @@ static int imgb_read(FILE *fp, oapv_imgb_t *img, int width, int height, int is_y
f_h = height;
}
else {
logerr("unsupported bit-depth (%d)\n", bit_depth);
logerr("ERR: unsupported bit-depth (%d)\n", bit_depth);
return -1;
}

Expand Down Expand Up @@ -493,14 +493,20 @@ static int imgb_write(char *fname, oapv_imgb_t *imgb)
{
unsigned char *p8;
int i, j, bd;
int chroma_format, bit_depth;
FILE *fp;

int chroma_format = OAPV_CS_GET_FORMAT(imgb->cs);
int bit_depth = OAPV_CS_GET_BIT_DEPTH(imgb->cs);
if(imgb == NULL) {
logerr("ERR: null image buffer in image write\n");
return -1;
}

chroma_format = OAPV_CS_GET_FORMAT(imgb->cs);
bit_depth = OAPV_CS_GET_BIT_DEPTH(imgb->cs);

fp = fopen(fname, "ab");
if(fp == NULL) {
logerr("cannot open file = %s\n", fname);
logerr("ERR: cannot open file = %s\n", fname);
return -1;
}
if(bit_depth == 8 && (chroma_format == OAPV_CF_YCBCR400 || chroma_format == OAPV_CF_YCBCR420 || chroma_format == OAPV_CF_YCBCR422 ||
Expand All @@ -514,7 +520,7 @@ static int imgb_write(char *fname, oapv_imgb_t *imgb)
bd = 2;
}
else {
logerr("cannot support the color space\n");
logerr("ERR: cannot support the color space\n");
fclose(fp);
return -1;
}
Expand All @@ -532,6 +538,35 @@ static int imgb_write(char *fname, oapv_imgb_t *imgb)
return 0;
}

// checks src/dst are compatible and both buffers hold the copy extent
static int imgb_cpy_is_valid(oapv_imgb_t *dst, oapv_imgb_t *src)
{
if(src == NULL || dst == NULL) {
logerr("ERR: null image buffer in image copy\n");
return 0;
}
if(src->np < 1 || src->np > OAPV_MAX_CC || dst->np != src->np) {
logerr("ERR: mismatched plane count in image copy\n");
return 0;
}
int src_bytes = OAPV_CS_GET_BYTE_DEPTH(src->cs);
int dst_bytes = OAPV_CS_GET_BYTE_DEPTH(dst->cs);
for(int i = 0; i < src->np; i++) {
int w = src->w[i] > src->aw[i] ? src->w[i] : src->aw[i];
int h = src->h[i] > src->ah[i] ? src->h[i] : src->ah[i];
if(src->a[i] == NULL || dst->a[i] == NULL || w < 0 || h < 0) {
logerr("ERR: invalid plane in image copy\n");
return 0;
}
if((long long)(h - 1) * src->s[i] + (long long)w * src_bytes > src->bsize[i] ||
(long long)(h - 1) * dst->s[i] + (long long)w * dst_bytes > dst->bsize[i]) {
logerr("ERR: buffer too small in image copy\n");
return 0;
}
}
return 1;
}

static void imgb_cpy_plane(oapv_imgb_t *dst, oapv_imgb_t *src)
{
int i, j;
Expand Down Expand Up @@ -654,9 +689,17 @@ static void imgb_cpy_shift_right(oapv_imgb_t *dst, oapv_imgb_t *src, int shift)
static void imgb_cpy(oapv_imgb_t *dst, oapv_imgb_t *src)
{
int i, bd_src, bd_dst;

if(!imgb_cpy_is_valid(dst, src)) return;

bd_src = OAPV_CS_GET_BIT_DEPTH(src->cs);
bd_dst = OAPV_CS_GET_BIT_DEPTH(dst->cs);

if(bd_src < 8 || bd_src > 16 || bd_dst < 8 || bd_dst > 16) {
logerr("ERR: unsupported bit depth in image copy\n");
return;
}

if(src->cs == dst->cs) {
imgb_cpy_plane(dst, src);
}
Expand Down Expand Up @@ -708,7 +751,7 @@ static void measure_psnr(oapv_imgb_t *org, oapv_imgb_t *rec, double psnr[4], int

for(j = 0; j < org->h[i]; j++) {
for(k = 0; k < org->w[i]; k++) {
sum[i] += (o[k] - r[k]) * (o[k] - r[k]);
sum[i] += (double)(o[k] - r[k]) * (o[k] - r[k]);
}

o += org->s[i];
Expand All @@ -734,7 +777,7 @@ static void measure_psnr(oapv_imgb_t *org, oapv_imgb_t *rec, double psnr[4], int
sum[i] += (((int)o[k] - (int)r[k]) >> 6) * (((int)o[k] - (int)r[k]) >> 6);
}
else {
sum[i] += (o[k] - r[k]) * (o[k] - r[k]);
sum[i] += (double)(o[k] - r[k]) * (o[k] - r[k]);
}
}
o = (unsigned short *)((unsigned char *)o + org->s[i]);
Expand All @@ -752,7 +795,7 @@ static int write_data(char *fname, unsigned char *data, int size)

fp = fopen(fname, "ab");
if(fp == NULL) {
logerr("cannot open the output file=%s\n", fname);
logerr("ERR: cannot open the output file=%s\n", fname);
return -1;
}
fwrite(data, 1, size, fp);
Expand All @@ -765,7 +808,7 @@ static int clear_data(char *fname)
FILE *fp;
fp = fopen(fname, "wb");
if(fp == NULL) {
logerr("cannot remove file (%s)\n", fname);
logerr("ERR: cannot remove file (%s)\n", fname);
return -1;
}
fclose(fp);
Expand Down
Loading
Loading