| 82 | } |
| 83 | |
| 84 | void readLengthEncodedString(String & s, ReadBuffer & buffer) |
| 85 | { |
| 86 | uint64_t len = readLengthEncodedNumber(buffer); |
| 87 | /// `len` is fully attacker-controlled (up to 2^64-1 via the 0xfe prefix). Grow the string in |
| 88 | /// bounded chunks as bytes actually arrive instead of resizing to `len` up front, so a bogus |
| 89 | /// length cannot trigger a huge pre-emptive allocation (pre-auth on the MySQL handshake path). |
| 90 | s.clear(); |
| 91 | while (s.size() < len) |
| 92 | { |
| 93 | if (buffer.eof()) |
| 94 | throw Exception(ErrorCodes::CANNOT_READ_ALL_DATA, |
| 95 | "Cannot read all data for a length-encoded string. Expected: {}, read: {}", len, s.size()); |
| 96 | size_t chunk = std::min(static_cast<uint64_t>(buffer.available()), len - s.size()); |
| 97 | size_t old_size = s.size(); |
| 98 | s.resize(old_size + chunk); |
| 99 | buffer.readStrict(s.data() + old_size, chunk); |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | } |
| 104 | |