fix: bound aggregate nested property sets
This commit is contained in:
@@ -27,6 +27,11 @@ interface ObjectStreamHeader {
|
||||
osidStreamNotPresent: boolean;
|
||||
}
|
||||
|
||||
interface PropertySetParseContext {
|
||||
limits: OneNoteParserLimits;
|
||||
nestedSetCount: number;
|
||||
}
|
||||
|
||||
export function parseObjectPropSet(
|
||||
bytes: Uint8Array,
|
||||
reference: ChunkReference,
|
||||
@@ -77,7 +82,7 @@ function parseObjectPropSetReader(
|
||||
}
|
||||
}
|
||||
|
||||
const properties = readPropertySet(reader, limits, 0);
|
||||
const properties = readPropertySet(reader, { limits, nestedSetCount: 0 }, 0);
|
||||
return { objectIds, objectSpaceIds, contextIds, properties };
|
||||
}
|
||||
|
||||
@@ -180,9 +185,10 @@ function readCompactIds(reader: BinaryReader, count: number): CompactId[] {
|
||||
|
||||
function readPropertySet(
|
||||
reader: BinaryReader,
|
||||
limits: OneNoteParserLimits,
|
||||
context: PropertySetParseContext,
|
||||
depth: number
|
||||
): PropertySet {
|
||||
const { limits } = context;
|
||||
if (depth > limits.maxPropertyDepth) {
|
||||
throw new OneNoteParserError(
|
||||
'LIMIT_EXCEEDED',
|
||||
@@ -209,7 +215,7 @@ function readPropertySet(
|
||||
rawId,
|
||||
id: rawId & 0x03ffffff,
|
||||
type,
|
||||
value: readPropertyValue(reader, rawId, type, limits, depth),
|
||||
value: readPropertyValue(reader, rawId, type, context, depth),
|
||||
} satisfies PropertyEntry;
|
||||
});
|
||||
return { entries };
|
||||
@@ -219,9 +225,10 @@ function readPropertyValue(
|
||||
reader: BinaryReader,
|
||||
rawId: number,
|
||||
type: number,
|
||||
limits: OneNoteParserLimits,
|
||||
context: PropertySetParseContext,
|
||||
depth: number
|
||||
): PropertyValue {
|
||||
const { limits } = context;
|
||||
switch (type) {
|
||||
case 0x1:
|
||||
return { kind: 'empty' };
|
||||
@@ -262,19 +269,23 @@ function readPropertyValue(
|
||||
case 0xd:
|
||||
return { kind: 'contextIds', count: boundedCount(reader, limits) };
|
||||
case 0x10: {
|
||||
const countOffset = reader.offset;
|
||||
const count = boundedCount(reader, limits);
|
||||
reserveNestedPropertySets(context, count, countOffset);
|
||||
const id = reader.u32();
|
||||
const sets: PropertySet[] = [];
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
sets.push(readPropertySet(reader, limits, depth + 1));
|
||||
sets.push(readPropertySet(reader, context, depth + 1));
|
||||
}
|
||||
return { kind: 'propertyValues', id, sets };
|
||||
}
|
||||
case 0x11:
|
||||
case 0x11: {
|
||||
reserveNestedPropertySets(context, 1, reader.offset);
|
||||
return {
|
||||
kind: 'propertySet',
|
||||
set: readPropertySet(reader, limits, depth + 1),
|
||||
set: readPropertySet(reader, context, depth + 1),
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw new OneNoteParserError(
|
||||
'INVALID_STRUCTURE',
|
||||
@@ -284,6 +295,21 @@ function readPropertyValue(
|
||||
}
|
||||
}
|
||||
|
||||
function reserveNestedPropertySets(
|
||||
context: PropertySetParseContext,
|
||||
count: number,
|
||||
offset: number
|
||||
): void {
|
||||
if (count > context.limits.maxObjectReferences - context.nestedSetCount) {
|
||||
throw new OneNoteParserError(
|
||||
'LIMIT_EXCEEDED',
|
||||
`Nested PropertySet count exceeds ${context.limits.maxObjectReferences}`,
|
||||
{ offset, structure: 'Nested PropertySets' }
|
||||
);
|
||||
}
|
||||
context.nestedSetCount += count;
|
||||
}
|
||||
|
||||
function boundedCount(
|
||||
reader: BinaryReader,
|
||||
limits: OneNoteParserLimits
|
||||
|
||||
Reference in New Issue
Block a user