thorfdbg / libjpeg

A complete implementation of 10918-1 (JPEG) coming from jpeg.org (the ISO group) with extensions for HDR, lossless and alpha channel coding standardized as ISO/IEC 18477 (JPEG XT).
327 stars 81 forks source link

Infinite loop in JPEG::ReadInternal #76

Closed 0xdd96 closed 2 years ago

0xdd96 commented 2 years ago

version: latest commit https://github.com/thorfdbg/libjpeg/commit/842c7baef7808f12cad19b49b2efcfa9575dbc78 poc: poc command: ./jpeg poc /dev/null

Here is the backtrace in GDB:

pwndbg> backtrace
#0  0x000055555558fa8a in Image::StartParseFrame (this=0x5555557433a0, io=0x555555741ad0) at image.cpp:658
#1  0x0000555555584739 in JPEG::ReadInternal (this=0x5555557414b8, tags=0x7fffffffdcf0) at jpeg.cpp:286
#2  0x00005555555843de in JPEG::Read (this=0x5555557414b8, tags=0x7fffffffdcf0) at jpeg.cpp:210
#3  0x000055555557a23e in Reconstruct (infile=0x7fffffffe6cf "../../script/test-libjpeg/modify8", outfile=0x7fffffffe6f1 "/dev/null", colortrafo=1, alpha=0x0, upsample=true) at reconstruct.cpp:121
#4  0x00005555555715be in main (argc=3, argv=0x7fffffffe448) at main.cpp:747
#5  0x00007ffff7abf0b3 in __libc_start_main (main=0x55555556fac1 <main(int, char**)>, argc=3, argv=0x7fffffffe448, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe438) at ../csu/libc-start.c:308
#6  0x000055555556f5ee in _start ()

When marker==0xffd9, ParseFrameHeader will return NULL (line 627, image.cpp), which initializes m_pCurrent with NULL (line 667, image.cpp). https://github.com/thorfdbg/libjpeg/blob/842c7baef7808f12cad19b49b2efcfa9575dbc78/codestream/image.cpp#L621-L627 https://github.com/thorfdbg/libjpeg/blob/842c7baef7808f12cad19b49b2efcfa9575dbc78/codestream/image.cpp#L657-L678

Since m_bReceivedFrameHeadere is set to true after that (lne 672, image.cpp), further calls to StartParseFrame will keep returning m_pCurreent=NULL.

https://github.com/thorfdbg/libjpeg/blob/842c7baef7808f12cad19b49b2efcfa9575dbc78/interface/jpeg.cpp#L284-L353

Such behavior leads to an infinite loop in JPEG::ReadInternal. When m_pFrame==NULL (line 285, jpeg.cpp), it will invoke m_pImage->StartParseFrame to initialize it (line 286, jpeg.cpp). Since StartParseFrame keeps returning NULL in this case, the while loop from line 284-353 cannot terminate.

thorfdbg commented 2 years ago

This was fixed in the latest release. Thank you.