Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions javascript/packages/fory/lib/fory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,15 @@ export default class {
anySerializer: Serializer;
typeMeta = TypeMeta;
config: Config;
depth = 0;
maxDepth: number;

constructor(config?: Partial<Config>) {
this.config = this.initConfig(config);
this.maxDepth = config?.maxDepth ?? 50;
if (this.maxDepth < 2) {
throw new Error(`maxDepth must be >= 2 but got ${this.maxDepth}`);
}
this.binaryReader = new BinaryReader(this.config);
this.binaryWriter = new BinaryWriter(this.config);
this.referenceResolver = new ReferenceResolver(this.binaryReader);
Expand All @@ -57,6 +63,7 @@ export default class {
return {
refTracking: config?.refTracking !== null ? Boolean(config?.refTracking) : null,
useSliceString: Boolean(config?.useSliceString),
maxDepth: config?.maxDepth,
hooks: config?.hooks || {},
compatible: Boolean(config?.compatible),
};
Expand All @@ -66,6 +73,20 @@ export default class {
return this.config.compatible === true;
}

incReadDepth(): void {
this.depth++;
if (this.depth > this.maxDepth) {
throw new Error(
`Deserialization depth limit exceeded: ${this.depth} > ${this.maxDepth}. `
+ "The data may be malicious, or increase maxDepth if needed."
);
}
}

decReadDepth(): void {
this.depth--;
}

registerSerializer<T>(constructor: new () => T, customSerializer: CustomSerializer<T>): {
serializer: Serializer;
serialize(data: InputType<T> | null): PlatformBuffer;
Expand Down Expand Up @@ -145,6 +166,7 @@ export default class {
this.binaryReader.reset(bytes);
this.typeMetaResolver.reset();
this.metaStringResolver.reset();
this.depth = 0;
const bitmap = this.binaryReader.readUint8();
if ((bitmap & ConfigFlags.isNullFlag) === ConfigFlags.isNullFlag) {
return null;
Expand Down
16 changes: 13 additions & 3 deletions javascript/packages/fory/lib/gen/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,13 @@ export abstract class BaseSerializerGenerator implements SerializerGenerator {

readNoRef(assignStmt: (v: string) => string, refState: string): string {
return `
${this.readTypeInfo()}
${this.read(assignStmt, refState)};
fory.incReadDepth();
try {
Copy link
Copy Markdown
Collaborator

@chaokunyang chaokunyang Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the try finally will introduce extra cost. Please remove try finally, and refactor serialize/deserializae entry point, create resetWrite/resetRead methods, move code like:

    this.referenceResolver.resetRead();
    this.binaryReader.reset(bytes);
    this.typeMetaResolver.resetRead();
    this.metaStringResolver.resetRead();

into resetRead()

and move smililiar methods into resetWrite.

Then set depth to 0 in resetRead() and resetWrite.

Current referenceResolver/typeMetaResolver/metaStringResolver may lack some such methods, please take java as referencev and add to javascript

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

${this.readTypeInfo()}
${this.read(assignStmt, refState)};
} finally {
fory.decReadDepth();
}
`;
}

Expand All @@ -211,7 +216,12 @@ export abstract class BaseSerializerGenerator implements SerializerGenerator {
switch (${refFlag}) {
case ${RefFlags.NotNullValueFlag}:
case ${RefFlags.RefValueFlag}:
${this.read(assignStmt, `${refFlag} === ${RefFlags.RefValueFlag}`)}
fory.incReadDepth();
try {
${this.read(assignStmt, `${refFlag} === ${RefFlags.RefValueFlag}`)}
} finally {
fory.decReadDepth();
}
break;
case ${RefFlags.RefFlag}:
${assignStmt(this.builder.referenceResolver.getReadObject(this.builder.reader.readVarUInt32()))}
Expand Down
1 change: 1 addition & 0 deletions javascript/packages/fory/lib/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ export interface Config {
hps?: Hps;
refTracking: boolean | null;
useSliceString: boolean;
maxDepth?: number;
hooks: {
afterCodeGenerated?: (code: string) => string;
};
Expand Down
Loading
Loading