Added missing length size checks

+ code cleanup/refactoring
This commit is contained in:
Martin Tůma 2025-01-07 08:52:40 +01:00
parent 252ca8542a
commit 3c125c9a7a

View File

@ -40,13 +40,22 @@ static bool varint(CTX &ctx, T &val)
return false; return false;
} }
static bool length(CTX &ctx, qint32 &val)
{
if (TYPE(ctx.tag) != LEN)
return false;
if (!varint(ctx, val))
return false;
return (val > 0);
}
static bool str(CTX &ctx, QByteArray &val) static bool str(CTX &ctx, QByteArray &val)
{ {
qint32 len; qint32 len;
if (TYPE(ctx.tag) != LEN) if (!length(ctx, len))
return false;
if (!varint(ctx, len))
return false; return false;
if (ctx.bp + len > ctx.be) if (ctx.bp + len > ctx.be)
return false; return false;
@ -89,7 +98,7 @@ static bool packed(CTX &ctx, QVector<quint32> &vals)
if (TYPE(ctx.tag) == LEN) { if (TYPE(ctx.tag) == LEN) {
qint32 len; qint32 len;
if (!varint(ctx, len)) if (!varint(ctx, len) || len <= 0)
return false; return false;
const char *ee = ctx.bp + len; const char *ee = ctx.bp + len;
if (ee > ctx.be) if (ee > ctx.be)
@ -120,7 +129,7 @@ static bool skip(CTX &ctx)
len = 8; len = 8;
break; break;
case LEN: case LEN:
if (!varint(ctx, len)) if (!varint(ctx, len) || len <= 0)
return false; return false;
break; break;
case I32: case I32:
@ -139,16 +148,13 @@ static bool skip(CTX &ctx)
static bool value(CTX &ctx, QVariant &val) static bool value(CTX &ctx, QVariant &val)
{ {
if (TYPE(ctx.tag) != LEN)
return false;
qint32 len; qint32 len;
QByteArray ba; QByteArray ba;
quint64 num; quint64 num;
double dnum; double dnum;
float fnum; float fnum;
if (!varint(ctx, len)) if (!length(ctx, len))
return false; return false;
const char *ee = ctx.bp + len; const char *ee = ctx.bp + len;
@ -214,13 +220,10 @@ static bool value(CTX &ctx, QVariant &val)
static bool feature(CTX &ctx, Data::Feature &f) static bool feature(CTX &ctx, Data::Feature &f)
{ {
qint32 len;
quint32 e; quint32 e;
if (TYPE(ctx.tag) != LEN) if (!length(ctx, len))
return false;
qint32 len;
if (!varint(ctx, len))
return false; return false;
const char *ee = ctx.bp + len; const char *ee = ctx.bp + len;
@ -266,63 +269,58 @@ static bool feature(CTX &ctx, Data::Feature &f)
static bool layer(CTX &ctx, Data::Layer &l) static bool layer(CTX &ctx, Data::Layer &l)
{ {
if (FIELD(ctx.tag) == 3) { qint32 len;
if (TYPE(ctx.tag) != LEN)
if (!length(ctx, len))
return false;
const char *ee = ctx.bp + len;
if (ee > ctx.be)
return false;
while (ctx.bp < ee) {
if (!varint(ctx, ctx.tag))
return false; return false;
qint32 len; switch (FIELD(ctx.tag)) {
if (!varint(ctx, len)) case 1:
return false; if (!str(ctx, l.name))
return false;
const char *ee = ctx.bp + len; break;
if (ee > ctx.be) case 2:
return false; l.features.append(Data::Feature());
if (!feature(ctx, l.features.last()))
while (ctx.bp < ee) { return false;
if (!varint(ctx, ctx.tag)) break;
return false; case 3:
l.keys.append(QByteArray());
switch (FIELD(ctx.tag)) { if (!str(ctx, l.keys.last()))
case 1: return false;
if (!str(ctx, l.name)) break;
return false; case 4:
break; l.values.append(QVariant());
case 2: if (!value(ctx, l.values.last()))
l.features.append(Data::Feature()); return false;
if (!feature(ctx, l.features.last())) break;
return false; case 5:
break; if (TYPE(ctx.tag) != VARINT)
case 3: return false;
l.keys.append(QByteArray()); if (!varint(ctx, l.extent))
if (!str(ctx, l.keys.last())) return false;
return false; break;
break; case 15:
case 4: if (TYPE(ctx.tag) != VARINT)
l.values.append(QVariant()); return false;
if (!value(ctx, l.values.last())) if (!varint(ctx, l.version))
return false; return false;
break; break;
case 5: default:
if (TYPE(ctx.tag) != VARINT) if (!skip(ctx))
return false; return false;
if (!varint(ctx, l.extent))
return false;
break;
case 15:
if (TYPE(ctx.tag) != VARINT)
return false;
if (!varint(ctx, l.version))
return false;
break;
default:
if (!skip(ctx))
return false;
}
} }
}
return (ctx.bp == ee); return (ctx.bp == ee);
} else
return skip(ctx);
} }
bool Data::load(const QByteArray &ba) bool Data::load(const QByteArray &ba)
@ -332,9 +330,17 @@ bool Data::load(const QByteArray &ba)
while (ctx.bp < ctx.be) { while (ctx.bp < ctx.be) {
if (!varint(ctx, ctx.tag)) if (!varint(ctx, ctx.tag))
return false; return false;
_layers.append(Layer());
if (!layer(ctx, _layers.last())) switch (FIELD(ctx.tag)) {
return false; case 3:
_layers.append(Layer());
if (!layer(ctx, _layers.last()))
return false;
break;
default:
if (!skip(ctx))
return false;
}
} }
return (ctx.bp == ctx.be); return (ctx.bp == ctx.be);