Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Out of memory from small file #1570

Open
radarhere opened this issue Dec 24, 2024 · 1 comment
Open

Out of memory from small file #1570

radarhere opened this issue Dec 24, 2024 · 1 comment

Comments

@radarhere
Copy link
Contributor

Expected behavior and actual behavior.

I expect small files to use a small amount of memory. However, oss-fuzz finds the attached small file can trigger an out of memory error, using 2584mb of RAM.

Steps to reproduce the problem.

I've attempted to simplify the reproduction, and here is what I've come up with. It has the file as an array of integers, but it comes from the zip embedded below.

typedef struct {
    OPJ_UINT32 tile_index;
    OPJ_UINT32 data_size;
    OPJ_INT32 x0, y0, x1, y1;
    OPJ_UINT32 nb_comps;
} JPEG2KTILEINFO;

static OPJ_SIZE_T
j2k_read(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) {
    int data[] = {-1, 79, -1, 81, 0, 47, 0, 0, 0, 96, 0, 25, 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 3, 0, 0, 0, 21, 0, 0, 0, 0, 0, 3, 8, 44, -9, 7, 60, 4, 0, 39, -1, -1, 82, 0, 13, 5, 0, 47, -112, 1, 0, 0, 0, 0, 0, -127, -1, 92, 0, 4, 96, 49, -1, -112, 0, 10, 0, 0, 0, 0, 0, 15, 0, 1, -1, -109, -1};
    for (int i = 0; i < 87; i++ ) {
      ((char *)p_buffer)[i] = data[i];
    }
    return 87;
}

struct State {
    UINT8 *buffer;
};

struct State *state = malloc(sizeof(struct State));
opj_stream_t *stream = NULL;
opj_image_t *image = NULL;
opj_codec_t *codec = NULL;
opj_dparameters_t params;

stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, OPJ_TRUE);

opj_stream_set_read_function(stream, j2k_read);

opj_stream_set_user_data(stream, state, NULL);

opj_stream_set_user_data_length(stream, 87);

opj_set_default_decoder_parameters(&params);
params.cp_reduce = 0;
params.cp_layer = 0;

codec = opj_create_decompress(OPJ_CODEC_J2K);

opj_setup_decoder(codec, &params);

opj_read_header(stream, codec, &image);
JPEG2KTILEINFO tile_info;
OPJ_BOOL should_continue;

opj_read_tile_header(
	codec,
	stream,
	&tile_info.tile_index,
	&tile_info.data_size,
	&tile_info.x0,
	&tile_info.y0,
	&tile_info.x1,
	&tile_info.y1,
	&tile_info.nb_comps,
	&should_continue
);

image.zip

Operating system

Ubuntu 20.04

openjpeg version

2.5.3

If you have any thoughts about why there is a large amount of memory being used, or if you think it's reasonable that an 87 byte file can use that much memory, please let me know. Thanks

@radarhere
Copy link
Contributor Author

radarhere commented Dec 25, 2024

I suspect the answer to this is #1178 (comment)

This issue is a design one. The library pre-allocates precints and codeblocks related structures, such as tagtree, for a whole tile. In the case of POC, there are for example 37 million codeblocks for one precinct, which represents 4 GB of RAM for the codeblock working memory (and other GB for tagtree etc). Completely legit JPEG2000 images could be built with the same characteristics as those corrupted images, and with sufficient huge amount of RAM could be docoded. As fixing the design of openjpeg would be enormous work, a fix would probably to set some implementation-defined thresholds, not normally reached on "normal" images, and error out if they are reached, and let the user able to override them with some environment variable.

Could this problem at least be mitigated by raising an error if the user data does not have a minimum length needed to expand to the image size?

Or when strict mode is enabled, could an error be raised early since there needs to be an EOC marker, and there isn't one in this file?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant