Skip to content

Commit

Permalink
fix: check collisions of method ids with reserved ones not only for e…
Browse files Browse the repository at this point in the history
…xplicitly specified ones (#1052)

Namely:
- `supported_interfaces`
- `lazy_deployment_completed`
- `get_abi_ipfs`
  • Loading branch information
Gusarich authored Nov 18, 2024
1 parent 1a1e69a commit 83e1681
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 33 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- Collisions in getter method ids are now handled and reported properly: PR [#875](https://github.com/tact-lang/tact/pull/875)
- Collisions in getter method ids are now handled and reported properly: PR [#875](https://github.com/tact-lang/tact/pull/875), PR [#1052](https://github.com/tact-lang/tact/pull/1052)
- Docs: layout of tables, syntax highlighting, Chinese translations of sidebar separators: PR [#916](https://github.com/tact-lang/tact/pull/916)
- Non-null struct fields after null ones are treated correctly in Sandbox tests after updating `@ton/core` to 0.59.0: PR [#933](https://github.com/tact-lang/tact/pull/933)
- Prevent inline code snippets from changing their background color: PR [#935](https://github.com/tact-lang/tact/pull/935)
Expand Down
60 changes: 60 additions & 0 deletions src/types/__snapshots__/resolveStatements.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,66 @@ Line 8, col 13:
"
`;

exports[`resolveStatements should fail statements for getter-collision-with-reserved_opt1 1`] = `
"<unknown>:10:9: method ids cannot overlap with Tact reserved method ids: 113617, 115390, 121275
Line 10, col 9:
9 |
> 10 | get(115390) fun _lazy_deployment_completed(): String{
^~~~~~
11 | return "not ok";
"
`;

exports[`resolveStatements should fail statements for getter-collision-with-reserved_opt2 1`] = `
"<unknown>:10:9: method ids cannot overlap with Tact reserved method ids: 113617, 115390, 121275
Line 10, col 9:
9 |
> 10 | get(121275) fun _get_abi_ipfs(): Int{
^~~~~~
11 | return 123;
"
`;

exports[`resolveStatements should fail statements for getter-collision-with-reserved_opt3 1`] = `
"<unknown>:10:9: method ids cannot overlap with Tact reserved method ids: 113617, 115390, 121275
Line 10, col 9:
9 |
> 10 | get(113617) fun _supported_interfaces(): String{
^~~~~~
11 | return "ok";
"
`;

exports[`resolveStatements should fail statements for getter-collision-with-reserved1 1`] = `
"<unknown>:10:5: method ids cannot overlap with Tact reserved method ids: 113617, 115390, 121275
Line 10, col 5:
9 |
> 10 | get fun lazy_deployment_completed(): String{
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 | return "not ok";
"
`;

exports[`resolveStatements should fail statements for getter-collision-with-reserved2 1`] = `
"<unknown>:10:5: method ids cannot overlap with Tact reserved method ids: 113617, 115390, 121275
Line 10, col 5:
9 |
> 10 | get fun get_abi_ipfs(): Int{
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 | return 123;
"
`;

exports[`resolveStatements should fail statements for getter-collision-with-reserved3 1`] = `
"<unknown>:10:5: method ids cannot overlap with Tact reserved method ids: 113617, 115390, 121275
Line 10, col 5:
9 |
> 10 | get fun supported_interfaces(): String{
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 | return "ok";
"
`;

exports[`resolveStatements should fail statements for getter-collision-with-trait 1`] = `
"<unknown>:4:13: Method ID collision: getter 'pko' has the same method ID 103057 as getter 'getter1'
Pick a different getter name or explicit method ID to avoid collisions
Expand Down
70 changes: 38 additions & 32 deletions src/types/resolveStatements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,40 @@ export function resolveStatements(ctx: CompilerContext) {
return ctx;
}

function checkMethodId(methodId: bigint, loc: SrcInfo) {
// method ids are 19-bit signed integers
if (methodId < -(2n ** 18n) || methodId >= 2n ** 18n) {
throwConstEvalError(
"method ids must fit 19-bit signed integer range",
true,
loc,
);
}
// method ids -4, -3, -2, -1, 0 ... 2^14 - 1 (inclusive) are kind of reserved by TVM
// for the upper bound see F12_n (CALL) TVM instruction
// and many small ids will be taken by internal procedures
//
// also, some ids are taken by the getters generated by Tact:
// supported_interfaces -> 113617
// lazy_deployment_completed -> 115390
// get_abi_ipfs -> 121275
if (-4n <= methodId && methodId < 2n ** 14n) {
throwConstEvalError(
"method ids cannot overlap with the TVM reserved ids: -4, -3, -2, -1, 0 ... 2^14 - 1",
true,
loc,
);
}
const tactGeneratedGetterMethodIds = [113617n, 115390n, 121275n];
if (tactGeneratedGetterMethodIds.includes(methodId)) {
throwConstEvalError(
`method ids cannot overlap with Tact reserved method ids: ${tactGeneratedGetterMethodIds.map((n) => n.toString()).join(", ")}`,
true,
loc,
);
}
}

function getMethodId(
funcDescr: FunctionDescription,
ctx: CompilerContext,
Expand All @@ -1001,39 +1035,11 @@ function getMethodId(
evalConstantExpression(optMethodId, ctx),
optMethodId.loc,
);
// method ids are 19-bit signed integers
if (methodId < -(2n ** 18n) || methodId >= 2n ** 18n) {
throwConstEvalError(
"method ids must fit 19-bit signed integer range",
true,
optMethodId!.loc,
);
}
// method ids -4, -3, -2, -1, 0 ... 2^14 - 1 (inclusive) are kind of reserved by TVM
// for the upper bound see F12_n (CALL) TVM instruction
// and many small ids will be taken by internal procedures
//
// also, some ids are taken by the getters generated by Tact:
// supported_interfaces -> 113617
// lazy_deployment_completed -> 115390
// get_abi_ipfs -> 121275
if (-4n <= methodId && methodId < 2n ** 14n) {
throwConstEvalError(
"method ids cannot overlap with the TVM reserved ids: -4, -3, -2, -1, 0 ... 2^14 - 1",
true,
optMethodId!.loc,
);
}
const tactGeneratedGetterMethodIds = [113617n, 115390n, 121275n];
if (tactGeneratedGetterMethodIds.includes(methodId)) {
throwConstEvalError(
`method ids cannot overlap with Tact reserved method ids: ${tactGeneratedGetterMethodIds.map((n) => n.toString()).join(", ")}`,
true,
optMethodId!.loc,
);
}
checkMethodId(methodId, optMethodId.loc);
return Number(methodId);
} else {
return (crc16(funcDescr.name) & 0xffff) | 0x10000;
const methodId = (crc16(funcDescr.name) & 0xffff) | 0x10000;
checkMethodId(BigInt(methodId), funcDescr.ast.loc);
return methodId;
}
}
13 changes: 13 additions & 0 deletions src/types/stmts-failed/getter-collision-with-reserved1.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
primitive String;

trait BaseTrait { }

contract TestContract {
get fun getter1() {
return;
}

get fun lazy_deployment_completed(): String{
return "not ok";
}
}
13 changes: 13 additions & 0 deletions src/types/stmts-failed/getter-collision-with-reserved2.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
primitive Int;

trait BaseTrait { }

contract TestContract {
get fun getter1() {
return;
}

get fun get_abi_ipfs(): Int{
return 123;
}
}
13 changes: 13 additions & 0 deletions src/types/stmts-failed/getter-collision-with-reserved3.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
primitive String;

trait BaseTrait { }

contract TestContract {
get fun getter1() {
return;
}

get fun supported_interfaces(): String{
return "ok";
}
}
13 changes: 13 additions & 0 deletions src/types/stmts-failed/getter-collision-with-reserved_opt1.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
primitive String;

trait BaseTrait { }

contract TestContract {
get fun getter1() {
return;
}

get(115390) fun _lazy_deployment_completed(): String{
return "not ok";
}
}
13 changes: 13 additions & 0 deletions src/types/stmts-failed/getter-collision-with-reserved_opt2.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
primitive Int;

trait BaseTrait { }

contract TestContract {
get fun getter1() {
return;
}

get(121275) fun _get_abi_ipfs(): Int{
return 123;
}
}
13 changes: 13 additions & 0 deletions src/types/stmts-failed/getter-collision-with-reserved_opt3.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
primitive String;

trait BaseTrait { }

contract TestContract {
get fun getter1() {
return;
}

get(113617) fun _supported_interfaces(): String{
return "ok";
}
}

0 comments on commit 83e1681

Please sign in to comment.