Skip to content

Commit

Permalink
Parse error on identifiers that are too long.
Browse files Browse the repository at this point in the history
SnarkVM requires that identifiers fit in a field
element.
  • Loading branch information
mikebenfield committed Nov 6, 2024
1 parent 4afc757 commit 47d78cd
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 33 deletions.
22 changes: 19 additions & 3 deletions compiler/parser/src/parser/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use crate::{Token, tokenizer::*};

use leo_ast::*;
use leo_errors::{ParserError, ParserWarning, Result, emitter::Handler};
use leo_span::{Span, Symbol};
use leo_span::{Span, Symbol, symbol::with_session_globals};

use snarkvm::prelude::Network;
use snarkvm::prelude::{Field, Network};

use std::{fmt::Display, marker::PhantomData, mem};

Expand Down Expand Up @@ -146,7 +146,9 @@ impl<'a, N: Network> ParserContext<'a, N> {
pub(super) fn eat_identifier(&mut self) -> Option<Identifier> {
if let Token::Identifier(name) = self.token.token {
self.bump();
return Some(self.mk_ident_prev(name));
let identifier = self.mk_ident_prev(name);
self.check_identifier(&identifier);
return Some(identifier);
}
None
}
Expand Down Expand Up @@ -257,4 +259,18 @@ impl<'a, N: Network> ParserContext<'a, N> {
pub(super) fn peek_is_left_par(&self) -> bool {
matches!(self.token.token, Token::LeftParen)
}

/// Error on identifiers that are longer than SnarkVM allows.
pub(crate) fn check_identifier(&self, identifier: &Identifier) {
let field_capacity_bytes: usize = Field::<N>::SIZE_IN_DATA_BITS / 8;
let len = with_session_globals(|sg| identifier.name.as_str(sg, |s| s.len()));
if len > field_capacity_bytes {
self.emit_err(ParserError::identifier_too_long(
identifier.name,
len,
field_capacity_bytes,
identifier.span,
));
}
}
}
7 changes: 7 additions & 0 deletions errors/src/errors/parser/parser_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,4 +365,11 @@ create_messages!(
msg: format!("Digit {digit} invalid in radix {radix} (token {token})."),
help: None,
}

@formatted
identifier_too_long {
args: (ident: impl Display, length: usize, max_length: usize),
msg: format!("Identifier {ident} is too long ({length} bytes; maximum is {max_length})"),
help: None,
}
);
2 changes: 1 addition & 1 deletion tests/expectations/compiler/examples/token.out
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace = "Compile"
expectation = "Pass"
outputs = [[{ compile = [{ initial_symbol_table = "8177e627a92d25f99122bb67b846cb21a98d38ec1a3df6bc48765113e814de49", type_checked_symbol_table = "544a9d535b04db44d4054ffd9120d6fa48f31e4300f657ecd78b109d5a325124", unrolled_symbol_table = "544a9d535b04db44d4054ffd9120d6fa48f31e4300f657ecd78b109d5a325124", initial_ast = "2f8d55ea61fa7fb52258aaefa5571ecf1c200b18e4d4b59139682c3c31c17f2b", unrolled_ast = "2f8d55ea61fa7fb52258aaefa5571ecf1c200b18e4d4b59139682c3c31c17f2b", ssa_ast = "5337c07ebb026dacba7cdf0eea8bcfd0139aac6c55b48c1c9ff75e79e9e7f332", flattened_ast = "28aa94e6823d7626c58140ce27cef1019a12aab8f89be54dd7eefdaf8885769d", destructured_ast = "466205d5e4e8326dc655be74eabdb284a2c3836430cd881c7e96f6826fe4d215", inlined_ast = "cfb86cdbfc0965637504ba9bd5a251dd9da2fd656e779d3fbb139e421370cd0b", dce_ast = "cfb86cdbfc0965637504ba9bd5a251dd9da2fd656e779d3fbb139e421370cd0b", bytecode = """
outputs = [[{ compile = [{ initial_symbol_table = "e6630be283ece8f60bf19e68c600817b0ef278c19d7aef9fc3e5b31b00b060db", type_checked_symbol_table = "970ae60a9c72622950585cac77be9fa761471e17d2e5b4eb531790b342c6ff19", unrolled_symbol_table = "970ae60a9c72622950585cac77be9fa761471e17d2e5b4eb531790b342c6ff19", initial_ast = "b0916e5119f9754e055c2ca01281208939521e39bceebeb5a1e90f68d22aeffb", unrolled_ast = "b0916e5119f9754e055c2ca01281208939521e39bceebeb5a1e90f68d22aeffb", ssa_ast = "1546802d24cea35bc03a21e4796079a1e3e102e7b3afbc48fb6c0124b90083bf", flattened_ast = "1c4beac4af82905f22419f8ee99cc535cbdd88dfb63c418d645b0d487791e95f", destructured_ast = "e9bd9cb2760eebdc8187802df1d2e3f9ea4c8c8a709ac5eccc261412dbd3e168", inlined_ast = "c2e4f4eec7defbdeffc1a1e8be826907653f73e490a614fae5603fbe7c48e20d", dce_ast = "c2e4f4eec7defbdeffc1a1e8be826907653f73e490a614fae5603fbe7c48e20d", bytecode = """
program token.aleo;

record token:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace = "Compile"
expectation = "Pass"
outputs = [[{ compile = [{ initial_symbol_table = "56c4eea018bad5b00fa3584917fe6327a28220606b7ef3392dd4f52510eb836d", type_checked_symbol_table = "a53c4315ffbe58449d9ef772a8fab06c43082a1d24d3eb4240fd8c3be3ac0ad1", unrolled_symbol_table = "a53c4315ffbe58449d9ef772a8fab06c43082a1d24d3eb4240fd8c3be3ac0ad1", initial_ast = "31d6210343f8a439e9a731aa2b344a0a35bb4828fcbfb5b7f3d3c532aa0d49e0", unrolled_ast = "31d6210343f8a439e9a731aa2b344a0a35bb4828fcbfb5b7f3d3c532aa0d49e0", ssa_ast = "ed0d528c739439b087da26d083d1a1c6705e5e9b020f6dbb6d1510929df3079f", flattened_ast = "853653a2db1cb618cf7fe214cc90ff1ee6f952dbc6e945b6b3c4b34ca07e906d", destructured_ast = "0fa73a1e802c55fe76758295dbeb0e4a9340fd95c14b05b033fd9aec1a039fed", inlined_ast = "17df43530f88543010218898759c3459f380370012717bebaec75f9a27d40130", dce_ast = "17df43530f88543010218898759c3459f380370012717bebaec75f9a27d40130", bytecode = """
outputs = [[{ compile = [{ initial_symbol_table = "83233a4d6b86c488fed94d68788771c6d66e8db5d8cc19e944b83ce37957dc38", type_checked_symbol_table = "15213e27a07d404c060fba06a8846df7bf56af827ac8fce15f373c9257615522", unrolled_symbol_table = "15213e27a07d404c060fba06a8846df7bf56af827ac8fce15f373c9257615522", initial_ast = "044081cc738c05a86903cfb285e4b2994e436bba8663f87f11ee6b6e16fd6bca", unrolled_ast = "044081cc738c05a86903cfb285e4b2994e436bba8663f87f11ee6b6e16fd6bca", ssa_ast = "134737377e2e27801bd823e7d90d56b99021e8d09cbac924ac73881ef1c5e47f", flattened_ast = "e3c07d14b70ed9bd4f02aeb3b1adac0b797298b5abf4ec4fbab6c476f0cbe11c", destructured_ast = "c6975e528196ae4b38d166b1ffe7a192cf0fa438d4b61f066b0f1c10928a857a", inlined_ast = "03f567618b1eb4e8ac17544dba2c6cfe122aa84a9fa592ea79c459f851acc461", dce_ast = "03f567618b1eb4e8ac17544dba2c6cfe122aa84a9fa592ea79c459f851acc461", bytecode = """
program test.aleo;

struct TokenInfo:
Expand All @@ -10,11 +10,11 @@ mapping token_name_to_info:
key as field.public;
value as TokenInfo.public;

function add_new_liquidity_token:
async add_new_liquidity_token into r0;
output r0 as test.aleo/add_new_liquidity_token.future;
function add_new_token:
async add_new_token into r0;
output r0 as test.aleo/add_new_token.future;

finalize add_new_liquidity_token:
finalize add_new_token:
branch.eq false false to end_then_0_0;
branch.eq true true to end_otherwise_0_1;
position end_then_0_0;
Expand All @@ -30,11 +30,11 @@ finalize add_new_liquidity_token:
position end_then_0_2;
position end_otherwise_0_3;

function add_new_liquidity_token_2:
async add_new_liquidity_token_2 into r0;
output r0 as test.aleo/add_new_liquidity_token_2.future;
function add_new_token_2:
async add_new_token_2 into r0;
output r0 as test.aleo/add_new_token_2.future;

finalize add_new_liquidity_token_2:
finalize add_new_token_2:
cast 0u64 into r0 as TokenInfo;
get.or_use token_name_to_info[0field] r0 into r1;
is.eq r1.id 0u64 into r2;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
namespace = "Compile"
expectation = "Pass"
outputs = [[
{ compile = [{ initial_symbol_table = "3c7d293c37250980a5585057e47928a31e3436cd32119581540bf51f5728c388", type_checked_symbol_table = "091fb907ad9e6f299261d8d3b0d7eea3e1fe7b3d264462067710ef685b2270e1", unrolled_symbol_table = "091fb907ad9e6f299261d8d3b0d7eea3e1fe7b3d264462067710ef685b2270e1", initial_ast = "320a1254fe4e5e65832dcfac7cfce31f8e2d20330ee5d8db5dcb64db96b04e44", unrolled_ast = "320a1254fe4e5e65832dcfac7cfce31f8e2d20330ee5d8db5dcb64db96b04e44", ssa_ast = "8d254079e14cc38ec69727d94a05ef669becda48a4201d236c0342dd2ba0a3f4", flattened_ast = "8a66d1d4efdac63e56a023f6741662a55d93481dcb0465eeafe876642f373cfd", destructured_ast = "e2694d1e1b256ebff10109dbb78e7f2da7fbcc9abc1c9996ace63bba5567035c", inlined_ast = "c089d74e6e09f64fe710904fbd61bffc92bcd7bd20379c404a724963dbe06401", dce_ast = "d890c7170e9541f4e7244473dea35ce26477cddd2c46ff9135a759848d948a6f", bytecode = """
{ compile = [{ initial_symbol_table = "166a830271cd7aed158e10b2143c9a03d0c865a70a271bf5cfeaf8a8f262c203", type_checked_symbol_table = "757143c658f82ba1791344d51c7140ac9c8297f233a2cc664884077c1cc64314", unrolled_symbol_table = "757143c658f82ba1791344d51c7140ac9c8297f233a2cc664884077c1cc64314", initial_ast = "79ffb3d8e763376c66760a989189bd5e368d43b461c8b7b5bd5f3c73e8ae9de5", unrolled_ast = "79ffb3d8e763376c66760a989189bd5e368d43b461c8b7b5bd5f3c73e8ae9de5", ssa_ast = "b29cb93dd5f962916f19de735160a23956fb1e6c810955ebc29fc929901c5312", flattened_ast = "f0e1d047cdeaec52cff67fd951319f7470ce8be736bbbd52c496a43669469856", destructured_ast = "3280e116aee027d9e5190aac15f54346b5b421eba91c38521edf3fc9929614aa", inlined_ast = "3059d5cb88c797c5712687c7577c5c3203491dcd60d0a99a3110c019bec597b2", dce_ast = "aac0d236f00fc0900e42d2666600e08b8dba7ae5101e245de681984bd58bd5f5", bytecode = """
program test.aleo;

function some_function:
""", errors = "", warnings = "" }] },
{ compile = [{ initial_symbol_table = "d5bf3f05f5a0afc811a2238929940629213ae93d47a62c90227f0c413c717544", type_checked_symbol_table = "79511fe231f3462aabe4261e9a2f22aa91c54351f576656f9b6bf64b5d467495", unrolled_symbol_table = "79511fe231f3462aabe4261e9a2f22aa91c54351f576656f9b6bf64b5d467495", initial_ast = "c5160a46e1db93ff65609f2995f5a7c02537c60fc41ee5286939515a93ec5860", unrolled_ast = "c5160a46e1db93ff65609f2995f5a7c02537c60fc41ee5286939515a93ec5860", ssa_ast = "f47fd6ab0deb01d222b7b7bd3852ecffb6506a4acdbb3c45eefe44503cec2fcb", flattened_ast = "ec138eb7d296236a666ee95a2da4ff5f379c76c12e76e9e2483e1b2d431e3c3f", destructured_ast = "69ad728f2fcb556dfa10941bd582f6e6c3fcd8169052916af5aec4bb41f03305", inlined_ast = "09985facfd23d038614e4b5eabe6e400b47321c1a8e3f5ec2f27144c2cad76c1", dce_ast = "09985facfd23d038614e4b5eabe6e400b47321c1a8e3f5ec2f27144c2cad76c1", bytecode = """
{ compile = [{ initial_symbol_table = "1e205ff819685df06705278368d4faca19dd049298b85d05f0ad4c3e6c13dc1e", type_checked_symbol_table = "c362626ac4ce0b659fc44774d3bad60d9e7a2e4feb44b09917656d3dbb70f324", unrolled_symbol_table = "c362626ac4ce0b659fc44774d3bad60d9e7a2e4feb44b09917656d3dbb70f324", initial_ast = "44f5a4a58ea0ad1d550e86cc5bfe0c1dd2dafa73a3f6574d552c118d6c0b49de", unrolled_ast = "44f5a4a58ea0ad1d550e86cc5bfe0c1dd2dafa73a3f6574d552c118d6c0b49de", ssa_ast = "f3bac2abda495b5b0824176aabb1b3676c4e91f32bbcb8694f365dd30be939ff", flattened_ast = "5e68bcde8778abf57055975197dd060e0b23ddb476c517776f7a272c6978ef8c", destructured_ast = "6a6a4ef016de75c8016aef2fcdb0d547f585a508fbe41288fb8b5a5be36dcee5", inlined_ast = "262b92cab36ca99d4d4c090c9ceaa0afe4f1c0bca1490a320f2fe30533a279cd", dce_ast = "262b92cab36ca99d4d4c090c9ceaa0afe4f1c0bca1490a320f2fe30533a279cd", bytecode = """
program test.aleo;

function some_function:
Expand Down
23 changes: 23 additions & 0 deletions tests/expectations/parser/identifiers/long_identifier_fail.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace = "Parse"
expectation = "Fail"
outputs = ["""
Error [EPAR0370044]: Identifier S012345678901234567890123456789q too long (32 bytes; maximum is 31)
--> test:19:12
|
19 | struct S012345678901234567890123456789q {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error [EPAR0370044]: Identifier m012345678901234567890123456789q too long (32 bytes; maximum is 31)
--> test:20:9
|
20 | m012345678901234567890123456789q: u8,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error [EPAR0370044]: Identifier x012345678901234567890123456789q too long (32 bytes; maximum is 31)
--> test:23:14
|
23 | function x012345678901234567890123456789q(y012345678901234567890123456789q: u8) -> u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error [EPAR0370044]: Identifier y012345678901234567890123456789q too long (32 bytes; maximum is 31)
--> test:23:47
|
23 | function x012345678901234567890123456789q(y012345678901234567890123456789q: u8) -> u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"""]
13 changes: 7 additions & 6 deletions tests/tests/compiler/examples/token.leo
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ program token.aleo {
/* Transfer */
async transition transfer_public(public receiver: address, public amount: u64) -> Future {
// Transfer the tokens publicly, by invoking the computation on-chain.
return finalize_transfer_public(self.caller, receiver, amount);
return finalize_tr_public(self.caller, receiver, amount);
}

async function finalize_transfer_public(sender: address, receiver: address, amount: u64) {
async function finalize_tr_public(sender: address, receiver: address, amount: u64) {
// Decrements `account[sender]` by `amount`.
// If `account[sender]` does not exist, it will be created.
// If `account[sender] - amount` underflows, `transfer_public` is reverted.
Expand Down Expand Up @@ -97,10 +97,10 @@ program token.aleo {

// Output the sender's change record.
// Increment the token amount publicly for the token receiver.
return (remaining, finalize_transfer_private_to_public(receiver, amount));
return (remaining, finalize_tr_private_to_public(receiver, amount));
}

async function finalize_transfer_private_to_public(receiver: address, amount: u64) {
async function finalize_tr_private_to_public(receiver: address, amount: u64) {
// Increments `account[receiver]` by `amount`.
// If `account[receiver]` does not exist, it will be created.
// If `account[receiver] + amount` overflows, `transfer_private_to_public` is reverted.
Expand All @@ -119,10 +119,10 @@ program token.aleo {

// Output the receiver's record.
// Decrement the token amount of the caller publicly.
return (transferred, finalize_transfer_public_to_private(self.caller, amount));
return (transferred, finalize_tr_public_to_private(self.caller, amount));
}

async function finalize_transfer_public_to_private(public sender: address, public amount: u64) {
async function finalize_tr_public_to_private(public sender: address, public amount: u64) {
// Decrements `account[sender]` by `amount`.
// If `account[sender]` does not exist, it will be created.
// If `account[sender] - amount` underflows, `transfer_public_to_private` is reverted.
Expand All @@ -132,3 +132,4 @@ program token.aleo {

}


Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ program test.aleo {
mapping token_name_to_info: field => TokenInfo;


async transition add_new_liquidity_token_2() -> Future {
return finalize_add_new_liquidity_token_2();
async transition add_new_token_2() -> Future {
return finalize_add_new_token_2();
}


async function finalize_add_new_liquidity_token_2() {
async function finalize_add_new_token_2() {
let try_get_token: TokenInfo = Mapping::get_or_use(
token_name_to_info,
0field,
Expand Down
12 changes: 6 additions & 6 deletions tests/tests/compiler/finalize/only_finalize_with_flattening.leo
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ program test.aleo {
mapping token_name_to_info: field => TokenInfo;


async transition add_new_liquidity_token () -> Future {
return finalize_add_new_liquidity_token();
async transition add_new_token () -> Future {
return finalize_add_new_token();
}
async function finalize_add_new_liquidity_token() -> () {
async function finalize_add_new_token() -> () {
if (false) {
return;
}
Expand All @@ -33,12 +33,12 @@ program test.aleo {
}
}

async transition add_new_liquidity_token_2 () -> Future {
return finalize_add_new_liquidity_token_2();
async transition add_new_token_2 () -> Future {
return finalize_add_new_token_2();
}


async function finalize_add_new_liquidity_token_2() {
async function finalize_add_new_token_2() {
let try_get_token: TokenInfo = Mapping::get_or_use(
token_name_to_info,
0field,
Expand Down
6 changes: 3 additions & 3 deletions tests/tests/compiler/function/inline_expr_statement.leo
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ program test.aleo {
return 0u32;
}

inline another_function_that_returns_a_value(a: u32) -> u32 {
inline another_f_that_returns_a_value(a: u32) -> u32 {
return a * a;
}

transition some_function() {
function_that_returns_a_value();
let a: u32 = function_that_returns_a_value();
another_function_that_returns_a_value(a);
let b: u32 = another_function_that_returns_a_value(a);
another_f_that_returns_a_value(a);
let b: u32 = another_f_that_returns_a_value(a);
}
}
30 changes: 30 additions & 0 deletions tests/tests/parser/identifiers/long_identifier_fail.leo
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
namespace = "Parse"
expectation = "Fail"
*/

program test.aleo {
transition main() -> bool {
return true;
}

// These identifiers are 31 characters long and should be fine.
struct S012345678901234567890123456789 {
m012345678901234567890123456789: u8,
}

function x012345678901234567890123456789(y012345678901234567890123456789: u8) -> u8 {
let z012345678901234567890123456789: u8 = 1u8;
return z012345678901234567890123456789 + y012345678901234567890123456789;
}

// These identifiers are 32 characters long and should fail.
struct S012345678901234567890123456789q {
m012345678901234567890123456789q: u8,
}

function x012345678901234567890123456789q(y012345678901234567890123456789q: u8) -> u8 {
let z012345678901234567890123456789q: u8 = 1u8;
return z012345678901234567890123456789q + y012345678901234567890123456789q;
}
}

0 comments on commit 47d78cd

Please sign in to comment.