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

Crashes due to internal bad memory references when using reduce on a truncated file. #1459

Closed
John-Nagle opened this issue Mar 3, 2023 · 2 comments

Comments

@John-Nagle
Copy link

Expected behavior and actual behavior.

Decompressing a truncated file at lower resolution should work. In about 1 of 250 tries, it doesn't. The result can be either an error return or a bad memory access.

Possibly related to Issue #1427 , where a similar problem was observed in multi-thread mode.

This was originally discovered when a metaverse client called the Rust crate jpeg2k, which called the Rust foreign function interface crate jpeg2000-sys, which called OpenJPEG, which crashed. Here's the history of that bug, including Valgrind output.

Steps to reproduce the problem.

The problem can be reproduced with opj-decompress under Valgrind, which shows OpenJPEG referencing un-initialized memory.
The problem may be intermittent.

To generate the test-case:

wget -O full_image.j2k http://asset-cdn.glb.agni.lindenlab.com/?texture_id=36b68663-b68d-9923-bf10-0c55c52426b5
dd if=./full_image.j2k of=partial_0_44236.j2k bs=44237 count=1

Here is the command to trigger the uninitialized reads:

OPJ_NUM_THREADS=1 valgrind opj_decompress -allow-partial -i ./partial_0_44236.j2k -o test.png -r 2

Note that the file is 44237 bytes long (http range requests are inclusive on both ends).

Operating system

Ubuntu 22.04 LTS

openjpeg version

OpenJPEG 2.5.0, from Github.

@John-Nagle
Copy link
Author

t2.c, line 1150, looks suspicious. Valgrind shows trouble where that value is used.
l_remaining_length = (OPJ_UINT32)(p_src_data + p_max_length - l_header_data);

I'm not sure what's going on in that code, but it seems to me that there should be some kind of check there for going off the end of the input data. Since this occurs with truncated files, that's a likely source of trouble.

@John-Nagle
Copy link
Author

I've been looking at opj_t2_read_packet_header in t2.c. I don't see what's wrong, but it's clear that it's very vulnerable to any of those offsets being wrong. I'd suggest adding sanity checks in there.

Valgrind detects problems in both the C and Rust version in this area:

  if (l_cp->ppm == 1) { /* PPM */
        l_header_data_start = &l_cp->ppm_data;
        l_header_data = *l_header_data_start;
        l_modified_length_ptr = &(l_cp->ppm_len);

    } else if (p_tcp->ppt == 1) { /* PPT */
        l_header_data_start = &(p_tcp->ppt_data);
        l_header_data = *l_header_data_start;
        l_modified_length_ptr = &(p_tcp->ppt_len);
    } else { /* Normal Case */
        l_header_data_start = &(l_current_data);
        l_header_data = *l_header_data_start;
        l_remaining_length = (OPJ_UINT32)(p_src_data + p_max_length - l_header_data);
        l_modified_length_ptr = &(l_remaining_length);
    }

Something in there has a reference to un-initialized memory.

@rouault rouault closed this as completed in c33e3d4 Mar 7, 2023
rouault added a commit that referenced this issue Mar 7, 2023
opj_t2_skip_packet_data(): avoid out-of-bounds reads on truncated images in non-strict mode (fixes #1459)
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