fsparser: check lines length

This commit is contained in:
Gwenhael Goavec-Merou 2026-04-10 09:26:08 +02:00
parent 78ab322615
commit 7a69d8353a
1 changed files with 80 additions and 10 deletions

View File

@ -42,30 +42,50 @@ int FsParser::parseHeader()
std::istringstream lineStream(_raw_data); std::istringstream lineStream(_raw_data);
while (std::getline(lineStream, buffer, '\n')) { while (std::getline(lineStream, buffer, '\n')) {
/* store full/real file lenght */
ret += buffer.size() + 1; ret += buffer.size() + 1;
/* FIXME: a line can't be empty -> error */
if (buffer.empty())
break;
/* dos file */
if (buffer.back() == '\r')
buffer.pop_back();
/* FIXME: a line can't be empty -> error */
if (buffer.empty()) if (buffer.empty())
break; break;
/* drop all comment, base analyze on header */ /* drop all comment, base analyze on header */
if (buffer[0] == '/') if (buffer[0] == '/')
continue; continue;
if (buffer[buffer.size()-1] == '\r')
buffer.pop_back();
/* store each line in dedicated buffer for future use const size_t line_length = buffer.size();
*/
/* store each line in dedicated buffer for future use */
_lstRawData.push_back(buffer); _lstRawData.push_back(buffer);
/* only headers are parsed by next portion of code */
if (!in_header) if (!in_header)
continue; continue;
/* a line must have at least 8 1/0 for the key */
if (line_length < 8) {
printError("FsParser: Potential corrupted file");
return 0;
}
uint8_t c = bitToVal(buffer.substr(0, 8).c_str(), 8); uint8_t c = bitToVal(buffer.substr(0, 8).c_str(), 8);
uint8_t key = c & 0x7F; uint8_t key = c & 0x7F;
uint64_t val = bitToVal(buffer.c_str(), buffer.size()); /* the line length depends on key/information */
uint64_t val = bitToVal(buffer.c_str(), line_length);
char __buf[10]; char __buf[10];
int __buf_valid_bytes; int __buf_valid_bytes;
switch (key) { switch (key) {
case 0x06: /* idCode */ case 0x06: /* idCode */
if (line_length != 64) {
printError("FsParser: length too short for key 0x06");
return 0;
}
_idcode = (0xffffffff & val); _idcode = (0xffffffff & val);
__buf_valid_bytes = snprintf(__buf, 9, "%08x", _idcode); __buf_valid_bytes = snprintf(__buf, 9, "%08x", _idcode);
_hdr["idcode"] = std::string(__buf, __buf_valid_bytes); _hdr["idcode"] = std::string(__buf, __buf_valid_bytes);
@ -77,9 +97,17 @@ int FsParser::parseHeader()
_hdr["CheckSum"].resize(8, ' '); _hdr["CheckSum"].resize(8, ' ');
break; break;
case 0x0B: /* only present when bit_security is set */ case 0x0B: /* only present when bit_security is set */
if (line_length != 32) {
printError("FsParser: length too short for key 0x0B");
return 0;
}
_hdr["SecurityBit"] = "ON"; _hdr["SecurityBit"] = "ON";
break; break;
case 0x10: { case 0x10: {
if (line_length != 64) {
printError("FsParser: length too short for key 0x10");
return 0;
}
unsigned rate = (val >> 16) & 0xff; unsigned rate = (val >> 16) & 0xff;
if (rate) { if (rate) {
rate &= 0x7f; rate &= 0x7f;
@ -96,8 +124,16 @@ int FsParser::parseHeader()
break; break;
} }
case 0x12: /* unknown */ case 0x12: /* unknown */
if (line_length != 32) {
printError("FsParser: length too short for key 0x12");
return 0;
}
break; break;
case 0x51: case 0x51:
if (line_length != 64) {
printError("FsParser: length too short for key 0x51");
return 0;
}
/* /*
[23:16] : a value used to replace 8x 0x00 in compress mode [23:16] : a value used to replace 8x 0x00 in compress mode
[15: 8] : a value used to replace 4x 0x00 in compress mode [15: 8] : a value used to replace 4x 0x00 in compress mode
@ -108,6 +144,10 @@ int FsParser::parseHeader()
_2Zero = 0xff & (val >> 0); _2Zero = 0xff & (val >> 0);
break; break;
case 0x52: /* documentation issue */ case 0x52: /* documentation issue */
if (line_length != 64) {
printError("FsParser: length too short for key 0x52");
return 0;
}
uint32_t flash_addr; uint32_t flash_addr;
flash_addr = val & 0xffffffff; flash_addr = val & 0xffffffff;
__buf_valid_bytes = snprintf(__buf, 9, "%08x", flash_addr); __buf_valid_bytes = snprintf(__buf, 9, "%08x", flash_addr);
@ -117,6 +157,10 @@ int FsParser::parseHeader()
break; break;
case 0x3B: /* last header line with crc and cfg data length */ case 0x3B: /* last header line with crc and cfg data length */
/* documentation issue */ /* documentation issue */
if (line_length != 32) {
printError("FsParser: length too short for key 0x3B");
return 0;
}
in_header = false; in_header = false;
uint8_t crc; uint8_t crc;
crc = 0x01 & (val >> 23); crc = 0x01 & (val >> 23);
@ -148,8 +192,14 @@ int FsParser::parse()
* if true 0 -> 0, 1 -> 1 * if true 0 -> 0, 1 -> 1
*/ */
_bit_data.reserve(_raw_data.size() / 8);
for (auto &&line : _lstRawData) { for (auto &&line : _lstRawData) {
for (size_t i = 0; i < line.size(); i += 8) { const size_t line_length = line.size();
if ((line_length % 8) != 0) {
printError("FsParser: truncated line in bitstream data");
return EXIT_FAILURE;
}
for (size_t i = 0; i < line_length; i += 8) {
uint8_t data = bitToVal(&line[i], 8); uint8_t data = bitToVal(&line[i], 8);
_bit_data.push_back((_reverseByte) ? reverseByte(data) : data); _bit_data.push_back((_reverseByte) ? reverseByte(data) : data);
} }
@ -236,9 +286,20 @@ int FsParser::parse()
for (auto &&ll = _lstRawData.begin(); for (auto &&ll = _lstRawData.begin();
ll != _lstRawData.end(); ll++) { ll != _lstRawData.end(); ll++) {
std::string l = ""; std::string l = "";
std::string line = *ll; const std::string &line = *ll;
const size_t line_length = line.size();
if (line_length < static_cast<size_t>(drop)) {
printError("FsParser: truncated configuration line");
return EXIT_FAILURE;
}
if (_compressed) { if (_compressed) {
for (size_t i = 0; i < line.size()-drop; i+=8) { const size_t payload_len = line_length - drop;
if ((payload_len % 8) != 0) {
printError("FsParser: compressed line is not byte aligned");
return EXIT_FAILURE;
}
l.reserve(payload_len * 8);
for (size_t i = 0; i < payload_len; i += 8) {
uint8_t c = bitToVal((const char *)&line[i], 8); uint8_t c = bitToVal((const char *)&line[i], 8);
if (c == _8Zero) if (c == _8Zero)
l += std::string(8*8, '0'); l += std::string(8*8, '0');
@ -250,15 +311,24 @@ int FsParser::parse()
l += line.substr(i, 8); l += line.substr(i, 8);
} }
} else { } else {
l = line.substr(0, line.size() - drop); l = line.substr(0, line_length - drop);
} }
const size_t l_length = l.size();
/* store bit for checksum */ /* store bit for checksum */
tmp += l.substr(padding, l.size() - padding); if (static_cast<size_t>(padding) > l_length) {
printError("FsParser: invalid padding for configuration line");
return EXIT_FAILURE;
}
tmp += l.substr(padding, l_length - padding);
} }
/* checksum */ /* checksum */
_checksum = 0; _checksum = 0;
if ((tmp.size() % 16) != 0) {
printError("FsParser: checksum data is truncated");
return EXIT_FAILURE;
}
for (uint32_t pos = 0; pos < tmp.size(); pos+=16) for (uint32_t pos = 0; pos < tmp.size(); pos+=16)
_checksum += (uint16_t)bitToVal(&tmp[pos], 16); _checksum += (uint16_t)bitToVal(&tmp[pos], 16);