# HG changeset patch # User František Kučera # Date 1626631709 -7200 # Node ID caed9146f72fecf67c23827d4edafad425f94349 # Parent bf2c546f49d158b156c8eeb5ed2bc75f0d57174a parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory (typeHeader.length may contain insane numbers if input in isValidBER() is not valid ASN.1/BER) diff -r bf2c546f49d1 -r caed9146f72f src/lib/BasicASN1Reader.h --- a/src/lib/BasicASN1Reader.h Sun Jul 18 12:37:40 2021 +0200 +++ b/src/lib/BasicASN1Reader.h Sun Jul 18 20:08:29 2021 +0200 @@ -112,7 +112,28 @@ return h; } - void readNext() { + const std::string readString(size_t length) { + std::string result; + + for (size_t remaining = length; remaining;) { + size_t current = std::min(remaining, (size_t) 3); + result.resize(result.size() + current); + read((uint8_t*) result.data() + result.size() - current, current); + remaining -= current; + } + + return result; + } + + const std::vector readVector(size_t length) { + std::vector result; + std::string s = readString(length); // TODO: read directly to the vector + result.resize(length); + for (size_t i = 0; i < length; i++) result[i] = (uint8_t) s[i]; + return result; + } + + void processNext() { using TagClass = ASN1ContentHandler::TagClass; using PC = ASN1ContentHandler::PC; @@ -146,38 +167,24 @@ read((uint8_t*) & value, 1); handlers->writeBoolean(typeHeader, value); } else if (typeHeader.tag == UniversalType::Integer && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { - // TODO: check available bytes before allocating buffer - std::vector value(typeHeader.length, 0x00); - read(value.data(), typeHeader.length); + std::vector value = readVector(typeHeader.length); handlers->writeInteger(typeHeader, ASN1ContentHandler::Integer(value)); } else if (typeHeader.tag == UniversalType::ObjectIdentifier && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { std::vector value(typeHeader.length, 0x00); read(value.data(), typeHeader.length); handlers->writeOID(typeHeader,{value}); } else if (typeHeader.tag == UniversalType::UTF8String && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { - // TODO: check available bytes before allocating buffer - std::string s; - s.resize(typeHeader.length); - read((uint8_t*) s.data(), typeHeader.length); + std::string s = readString(typeHeader.length); handlers->writeTextString(typeHeader, s); } else if (typeHeader.tag == UniversalType::PrintableString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { // TODO: check encoding - // TODO: check available bytes before allocating buffer - std::string s; - s.resize(typeHeader.length); - read((uint8_t*) s.data(), typeHeader.length); + std::string s = readString(typeHeader.length); handlers->writeTextString(typeHeader, s); } else if (typeHeader.tag == UniversalType::OctetString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { - // TODO: check available bytes before allocating buffer - std::string s; - s.resize(typeHeader.length); - read((uint8_t*) s.data(), typeHeader.length); + std::string s = readString(typeHeader.length); if (processEncapsulatedContent(typeHeader, s) == false) handlers->writeOctetString(typeHeader, s); } else if (typeHeader.tag == UniversalType::BitString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { - // TODO: check available bytes before allocating buffer - std::string s; - s.resize(typeHeader.length); - read((uint8_t*) s.data(), typeHeader.length); + std::string s = readString(typeHeader.length); if (processEncapsulatedContent(typeHeader, s) == false) { std::vector bits; // TODO: throw exception on wrong padding or insufficient length? @@ -189,11 +196,8 @@ handlers->writeBitString(typeHeader, bits); } } else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { - // TODO: check available bytes before allocating buffer // TODO: check encoding - std::string s; - s.resize(typeHeader.length); - read((uint8_t*) s.data(), typeHeader.length); + std::string s = readString(typeHeader.length); ASN1ContentHandler::DateTime dateTime; @@ -219,10 +223,7 @@ } } else if (typeHeader.tag == UniversalType::GeneralizedTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { - // TODO: check available bytes before allocating buffer - std::string s; - s.resize(typeHeader.length); - read((uint8_t*) s.data(), typeHeader.length); + std::string s = readString(typeHeader.length); ASN1ContentHandler::DateTime dateTime; @@ -252,10 +253,7 @@ } else { // TODO: do not skip, parse - // TODO: check available bytes before allocating buffer - std::string s; - s.resize(typeHeader.length); - read((uint8_t*) s.data(), typeHeader.length); + std::string s = readString(typeHeader.length); handlers->writeSpecific(typeHeader, s); } @@ -327,7 +325,7 @@ protected: void update() override { - while (true) readNext(); + while (true) processNext(); } public: