@@ -20,6 +20,11 @@ static const char *TAG = "jpeg.decoder";
2020
2121static uint8_t jpeg_get_char (jpeg_dec_header_info_t * header_info )
2222{
23+ // Check if there are bytes left to read before decrementing buffer_left
24+ if (header_info -> buffer_left == 0 ) {
25+ ESP_LOGE (TAG , "Buffer underflow detected in jpeg_get_char: no more bytes left to read" );
26+ return 0 ;
27+ }
2328 uint8_t c = header_info -> buffer_offset [0 ];
2429 header_info -> buffer_offset ++ ;
2530 header_info -> header_size ++ ;
@@ -39,20 +44,26 @@ uint32_t jpeg_get_bytes(jpeg_dec_header_info_t *header_info, uint8_t num_bytes)
3944
4045esp_err_t jpeg_parse_appn_marker (jpeg_dec_header_info_t * header_info )
4146{
42- uint32_t skip_num = jpeg_get_bytes (header_info , 2 );
43- header_info -> buffer_offset += (skip_num - 2 );
44- header_info -> header_size += (skip_num - 2 );
45- header_info -> buffer_left -= (skip_num - 2 );
47+ uint16_t skip_num = jpeg_get_bytes (header_info , 2 );
48+ ESP_RETURN_ON_FALSE (skip_num >= 2 , ESP_ERR_INVALID_ARG , TAG , "Invalid APPn marker length: %" PRIu32 , skip_num );
49+ uint16_t bytes_to_skip = skip_num - 2 ;
50+ ESP_RETURN_ON_FALSE (header_info -> buffer_left >= bytes_to_skip , ESP_ERR_INVALID_ARG , TAG , "APPn marker data underflow for buffer_left: %" PRIu32 , header_info -> buffer_left );
51+ header_info -> buffer_offset += bytes_to_skip ;
52+ header_info -> header_size += bytes_to_skip ;
53+ header_info -> buffer_left -= bytes_to_skip ;
4654
4755 return ESP_OK ;
4856}
4957
5058esp_err_t jpeg_parse_com_marker (jpeg_dec_header_info_t * header_info )
5159{
52- uint32_t skip_num = jpeg_get_bytes (header_info , 2 );
53- header_info -> buffer_offset += (skip_num - 2 );
54- header_info -> header_size += (skip_num - 2 );
55- header_info -> buffer_left -= (skip_num - 2 );
60+ uint16_t skip_num = jpeg_get_bytes (header_info , 2 );
61+ ESP_RETURN_ON_FALSE (skip_num >= 2 , ESP_ERR_INVALID_ARG , TAG , "Invalid COM marker length: %" PRIu32 , skip_num );
62+ uint32_t bytes_to_skip = skip_num - 2 ;
63+ ESP_RETURN_ON_FALSE (header_info -> header_size >= bytes_to_skip , ESP_ERR_INVALID_ARG , TAG , "COM marker data underflow for header_size: %" PRIu32 , header_info -> header_size );
64+ header_info -> buffer_offset += bytes_to_skip ;
65+ header_info -> header_size += bytes_to_skip ;
66+ header_info -> buffer_left -= bytes_to_skip ;
5667 return ESP_OK ;
5768}
5869
@@ -61,21 +72,25 @@ esp_err_t jpeg_parse_dqt_marker(jpeg_dec_header_info_t *header_info)
6172 uint32_t n = 0 , i = 0 , prec = 0 ;
6273 uint32_t temp = 0 ;
6374
64- uint32_t length_num = jpeg_get_bytes (header_info , 2 );
75+ uint16_t length_num = jpeg_get_bytes (header_info , 2 );
76+ ESP_RETURN_ON_FALSE (length_num >= 2 , ESP_ERR_INVALID_ARG , TAG , "Invalid DQT marker length: %" PRIu32 , length_num );
6577 length_num -= 2 ;
6678
6779 while (length_num ) {
6880 n = jpeg_get_bytes (header_info , 1 );
6981 prec = n >> 4 ;
7082 n &= 0x0F ;
83+ ESP_RETURN_ON_FALSE (length_num >= 1 , ESP_ERR_INVALID_ARG , TAG , "DQT marker length error: %" PRIu32 , length_num );
7184 length_num -= 1 ;
7285
7386 // read quantization entries, in zig-zag order
7487 for (i = 0 ; i < 64 ; i ++ ) {
7588 temp = jpeg_get_bytes (header_info , 1 );
89+ ESP_RETURN_ON_FALSE (length_num >= 1 , ESP_ERR_INVALID_ARG , TAG , "DQT marker length error: %" PRIu32 , length_num );
7690 length_num -= 1 ;
7791 if (prec ) {
7892 temp = (temp << 8 ) + jpeg_get_bytes (header_info , 1 );
93+ ESP_RETURN_ON_FALSE (length_num >= 1 , ESP_ERR_INVALID_ARG , TAG , "DQT marker length error: %" PRIu32 , length_num );
7994 length_num -= 1 ;
8095 }
8196 header_info -> qt_tbl [n ][zigzag_arr [i ]] = temp ;
@@ -142,7 +157,10 @@ esp_err_t jpeg_parse_sof_marker(jpeg_dec_header_info_t *header_info)
142157esp_err_t jpeg_parse_dht_marker (jpeg_dec_header_info_t * header_info )
143158{
144159 // Recording num_left in DHT sector, not including length bytes (2 bytes).
145- uint32_t num_left = jpeg_get_bytes (header_info , 2 ) - 2 ;
160+ uint16_t raw_length = jpeg_get_bytes (header_info , 2 );
161+ // Check for integer underflow before subtraction
162+ ESP_RETURN_ON_FALSE (raw_length >= 2 , ESP_ERR_INVALID_ARG , TAG , "Invalid DHT marker length: %" PRIu32 , raw_length );
163+ uint16_t num_left = raw_length - 2 ;
146164 while (num_left ) {
147165 uint32_t np = 0 ;
148166
@@ -159,6 +177,8 @@ esp_err_t jpeg_parse_dht_marker(jpeg_dec_header_info_t *header_info)
159177 header_info -> huffcode [header_info -> huffinfo .type ][header_info -> huffinfo .id ][i ] = jpeg_get_bytes (header_info , 1 );
160178 }
161179
180+ // Check for integer underflow before subtraction
181+ ESP_RETURN_ON_FALSE (num_left >= (JPEG_HUFFMAN_BITS_LEN_TABLE_LEN + np + 1 ), ESP_ERR_INVALID_ARG , TAG , "DHT marker data underflow after parsing huffcode: %" PRIu32 , num_left );
162182 num_left -= (1 + JPEG_HUFFMAN_BITS_LEN_TABLE_LEN + np );
163183 }
164184
@@ -181,6 +201,7 @@ esp_err_t jpeg_parse_dri_marker(jpeg_dec_header_info_t *header_info)
181201esp_err_t jpeg_parse_sos_marker (jpeg_dec_header_info_t * header_info )
182202{
183203 // Got the SOS marker, but need to recover this and feed to 2DDMA.
204+ ESP_RETURN_ON_FALSE (header_info -> header_size >= 2 , ESP_ERR_INVALID_ARG , TAG , "SOS marker header_size underflow: %" PRIu32 , header_info -> header_size );
184205 header_info -> buffer_offset -= 2 ;
185206 header_info -> header_size -= 2 ;
186207 header_info -> buffer_left += 2 ;
@@ -191,6 +212,7 @@ esp_err_t jpeg_parse_inv_marker(jpeg_dec_header_info_t *header_info)
191212{
192213 // Got invalid 0xFFFF, (followed by a valid marker type)
193214 // Go one byte back, to skip the first 0xFF
215+ ESP_RETURN_ON_FALSE (header_info -> header_size >= 1 , ESP_ERR_INVALID_ARG , TAG , "INV marker header_size underflow: %" PRIu32 , header_info -> header_size );
194216 header_info -> buffer_offset -- ;
195217 header_info -> header_size -- ;
196218 header_info -> buffer_left ++ ;
0 commit comments