@@ -42,30 +42,50 @@ int FsParser::parseHeader()
4242 std::istringstream lineStream (_raw_data);
4343
4444 while (std::getline (lineStream, buffer, ' \n ' )) {
45+ /* store full/real file lenght */
4546 ret += buffer.size () + 1 ;
47+
48+ /* FIXME: a line can't be empty -> error */
49+ if (buffer.empty ())
50+ break ;
51+ /* dos file */
52+ if (buffer.back () == ' \r ' )
53+ buffer.pop_back ();
54+
55+ /* FIXME: a line can't be empty -> error */
4656 if (buffer.empty ())
4757 break ;
4858 /* drop all comment, base analyze on header */
4959 if (buffer[0 ] == ' /' )
5060 continue ;
51- if (buffer[buffer.size ()-1 ] == ' \r ' )
52- buffer.pop_back ();
5361
54- /* store each line in dedicated buffer for future use
55- */
62+ const size_t line_length = buffer.size ();
63+
64+ /* store each line in dedicated buffer for future use */
5665 _lstRawData.push_back (buffer);
5766
67+ /* only headers are parsed by next portion of code */
5868 if (!in_header)
5969 continue ;
6070
71+ /* a line must have at least 8 1/0 for the key */
72+ if (line_length < 8 ) {
73+ printError (" FsParser: Potential corrupted file" );
74+ return 0 ;
75+ }
6176 uint8_t c = bitToVal (buffer.substr (0 , 8 ).c_str (), 8 );
6277 uint8_t key = c & 0x7F ;
63- uint64_t val = bitToVal (buffer.c_str (), buffer.size ());
78+ /* the line length depends on key/information */
79+ uint64_t val = bitToVal (buffer.c_str (), line_length);
6480
6581 char __buf[10 ];
6682 int __buf_valid_bytes;
6783 switch (key) {
6884 case 0x06 : /* idCode */
85+ if (line_length != 64 ) {
86+ printError (" FsParser: length too short for key 0x06" );
87+ return 0 ;
88+ }
6989 _idcode = (0xffffffff & val);
7090 __buf_valid_bytes = snprintf (__buf, 9 , " %08x" , _idcode);
7191 _hdr[" idcode" ] = std::string (__buf, __buf_valid_bytes);
@@ -77,9 +97,17 @@ int FsParser::parseHeader()
7797 _hdr[" CheckSum" ].resize (8 , ' ' );
7898 break ;
7999 case 0x0B : /* only present when bit_security is set */
100+ if (line_length != 32 ) {
101+ printError (" FsParser: length too short for key 0x0B" );
102+ return 0 ;
103+ }
80104 _hdr[" SecurityBit" ] = " ON" ;
81105 break ;
82106 case 0x10 : {
107+ if (line_length != 64 ) {
108+ printError (" FsParser: length too short for key 0x10" );
109+ return 0 ;
110+ }
83111 unsigned rate = (val >> 16 ) & 0xff ;
84112 if (rate) {
85113 rate &= 0x7f ;
@@ -96,8 +124,16 @@ int FsParser::parseHeader()
96124 break ;
97125 }
98126 case 0x12 : /* unknown */
127+ if (line_length != 32 ) {
128+ printError (" FsParser: length too short for key 0x12" );
129+ return 0 ;
130+ }
99131 break ;
100132 case 0x51 :
133+ if (line_length != 64 ) {
134+ printError (" FsParser: length too short for key 0x51" );
135+ return 0 ;
136+ }
101137 /*
102138 [23:16] : a value used to replace 8x 0x00 in compress mode
103139 [15: 8] : a value used to replace 4x 0x00 in compress mode
@@ -108,6 +144,10 @@ int FsParser::parseHeader()
108144 _2Zero = 0xff & (val >> 0 );
109145 break ;
110146 case 0x52 : /* documentation issue */
147+ if (line_length != 64 ) {
148+ printError (" FsParser: length too short for key 0x52" );
149+ return 0 ;
150+ }
111151 uint32_t flash_addr;
112152 flash_addr = val & 0xffffffff ;
113153 __buf_valid_bytes = snprintf (__buf, 9 , " %08x" , flash_addr);
@@ -117,6 +157,10 @@ int FsParser::parseHeader()
117157 break ;
118158 case 0x3B : /* last header line with crc and cfg data length */
119159 /* documentation issue */
160+ if (line_length != 32 ) {
161+ printError (" FsParser: length too short for key 0x3B" );
162+ return 0 ;
163+ }
120164 in_header = false ;
121165 uint8_t crc;
122166 crc = 0x01 & (val >> 23 );
@@ -148,8 +192,14 @@ int FsParser::parse()
148192 * if true 0 -> 0, 1 -> 1
149193 */
150194
195+ _bit_data.reserve (_raw_data.size () / 8 );
151196 for (auto &&line : _lstRawData) {
152- for (size_t i = 0 ; i < line.size (); i += 8 ) {
197+ const size_t line_length = line.size ();
198+ if ((line_length % 8 ) != 0 ) {
199+ printError (" FsParser: truncated line in bitstream data" );
200+ return EXIT_FAILURE;
201+ }
202+ for (size_t i = 0 ; i < line_length; i += 8 ) {
153203 uint8_t data = bitToVal (&line[i], 8 );
154204 _bit_data.push_back ((_reverseByte) ? reverseByte (data) : data);
155205 }
@@ -236,9 +286,20 @@ int FsParser::parse()
236286 for (auto &&ll = _lstRawData.begin ();
237287 ll != _lstRawData.end (); ll++) {
238288 std::string l = " " ;
239- std::string line = *ll;
289+ const std::string &line = *ll;
290+ const size_t line_length = line.size ();
291+ if (line_length < static_cast <size_t >(drop)) {
292+ printError (" FsParser: truncated configuration line" );
293+ return EXIT_FAILURE;
294+ }
240295 if (_compressed) {
241- for (size_t i = 0 ; i < line.size ()-drop; i+=8 ) {
296+ const size_t payload_len = line_length - drop;
297+ if ((payload_len % 8 ) != 0 ) {
298+ printError (" FsParser: compressed line is not byte aligned" );
299+ return EXIT_FAILURE;
300+ }
301+ l.reserve (payload_len * 8 );
302+ for (size_t i = 0 ; i < payload_len; i += 8 ) {
242303 uint8_t c = bitToVal ((const char *)&line[i], 8 );
243304 if (c == _8Zero)
244305 l += std::string (8 *8 , ' 0' );
@@ -250,15 +311,24 @@ int FsParser::parse()
250311 l += line.substr (i, 8 );
251312 }
252313 } else {
253- l = line.substr (0 , line. size () - drop);
314+ l = line.substr (0 , line_length - drop);
254315 }
316+ const size_t l_length = l.size ();
255317
256318 /* store bit for checksum */
257- tmp += l.substr (padding, l.size () - padding);
319+ if (static_cast <size_t >(padding) > l_length) {
320+ printError (" FsParser: invalid padding for configuration line" );
321+ return EXIT_FAILURE;
322+ }
323+ tmp += l.substr (padding, l_length - padding);
258324 }
259325
260326 /* checksum */
261327 _checksum = 0 ;
328+ if ((tmp.size () % 16 ) != 0 ) {
329+ printError (" FsParser: checksum data is truncated" );
330+ return EXIT_FAILURE;
331+ }
262332 for (uint32_t pos = 0 ; pos < tmp.size (); pos+=16 )
263333 _checksum += (uint16_t )bitToVal (&tmp[pos], 16 );
264334
0 commit comments