Commit 281ad665 authored by Volker Krause's avatar Volker Krause
Browse files

Add proper error handling for uPER decoding

Rather than asserting this switches the decoder into an error state now
and invalidates the decoded result.
parent 1c89ddad
......@@ -39,7 +39,10 @@ int64_t UPERDecoder::readConstrainedWholeNumber(int64_t minimum, int64_t maximum
int64_t UPERDecoder::readUnconstrainedWholeNumber()
{
const auto len = readLengthDeterminant();
assert(len <= 8); // TODO
if (len > 8) {
setError("Encountered INTEGER bigger than 64bit, not implemented.");
return 0;
}
int64_t result = m_data.valueAtMSB<int64_t>(m_idx, 8 * len);
m_idx += 8 * len;
return result; // TODO convert negative numbers
......@@ -53,8 +56,7 @@ UPERDecoder::size_type UPERDecoder::readLengthDeterminant()
return len;
}
// TODO
assert(false);
setError("Encountered not implemented length determinant variant.");
return 0;
}
......@@ -150,3 +152,18 @@ QList<QString> UPERDecoder::readSequenceOfUtf8String()
}
return result;
}
bool UPERDecoder::hasError() const
{
return !m_error.isEmpty();
}
QByteArray UPERDecoder::errorMessage() const
{
return m_error;
}
void UPERDecoder::setError(const char *msg)
{
m_error = "uPER decoding error at offset " + QByteArray::number((qint64)m_idx) + ": " + msg;
}
......@@ -103,7 +103,10 @@ public:
template <typename T>
inline T readEnumeratedWithExtensionMarker()
{
assert(!readBoolean()); // TODO
if (readBoolean()) {
setError("CHOICE with extension marker set not implemented.");
return {};
}
return readEnumerated<T>();
}
......@@ -113,13 +116,29 @@ public:
template <typename... Ts>
inline QVariant readChoiceWithExtensionMarker()
{
assert(!readBoolean()); // TODO
if (readBoolean()) {
setError("CHOICE with extension marker set not implemented.");
return {};
}
constexpr auto count = sizeof...(Ts);
const auto choiceIdx = readConstrainedWholeNumber(0, count - 1);
assert(choiceIdx < (int)count); // TODO
if (choiceIdx > (int)count) {
setError("Invalid CHOICE index.");
return {};
}
return readChoiceElement<Ts...>(choiceIdx);
}
/** Reading at any point encountered an error.
* As uPER gives us no way to recover from that, everything
* read has to be considered invalid.
*/
bool hasError() const;
QByteArray errorMessage() const;
/** Put the decoder into the error state. */
void setError(const char *msg);
private:
QByteArray readIA5StringData(size_type len);
......@@ -142,6 +161,7 @@ private:
BitVectorView m_data;
size_type m_idx = {};
QByteArray m_error;
};
}
......
......@@ -75,7 +75,10 @@ private: \
std::bitset<_uper_OptionalCount> m_optionals; \
inline void decodeSequence(UPERDecoder &decoder) { \
if constexpr (_uper_ExtensionMarker) { \
assert(!decoder.readBoolean()); /* TODO either handle this properly, or switch to an error state. */ \
if (decoder.readBoolean()) { \
decoder.setError("SEQUENCE with extension marker set not implemented."); \
return; \
} \
} \
m_optionals = decoder.readBitset<_uper_OptionalCount>(); \
}
......
......@@ -5,10 +5,9 @@
#include "fcbticket.h"
#include "logging.h"
#include "asn1/uperdecoder.h"
#include <QDebug>
#define FCB_READ_CONSTRAINED_INT(Name, Min, Max) \
if (Name ## IsSet()) \
Name = decoder.readConstrainedWholeNumber(Min, Max)
......@@ -775,6 +774,10 @@ Fcb::UicRailTicketData::UicRailTicketData(const Uic9183Block &block)
{
UPERDecoder decoder(BitVectorView(std::string_view(block.content(), block.contentSize())));
decode(decoder);
if (decoder.hasError()) {
qCWarning(Log) << decoder.errorMessage();
m_block = {};
}
}
void Fcb::UicRailTicketData::decode(UPERDecoder &decoder)
......@@ -786,4 +789,9 @@ void Fcb::UicRailTicketData::decode(UPERDecoder &decoder)
FCB_READ_CUSTOM(controlDetail)
}
bool Fcb::UicRailTicketData::isValid() const
{
return !m_block.isNull();
}
#include "moc_fcbticket.cpp"
......@@ -928,6 +928,8 @@ public:
static constexpr const char RecordId[] = "U_FLEX";
bool isValid() const;
private:
Uic9183Block m_block;
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment