Skip to content

Commit

Permalink
Reject env.json if there are duplicate export names, fix #189 (#994)
Browse files Browse the repository at this point in the history
* Reject env.json if there are duplicate export names, fix #189

* Require export names to be sequential, fix env.json

* Clarify env.json docs around arrays that have len elements rather than len bytes, fix #749
  • Loading branch information
graydon authored Aug 15, 2023
1 parent c0f1ecb commit db2e682
Show file tree
Hide file tree
Showing 21 changed files with 135 additions and 70 deletions.
136 changes: 68 additions & 68 deletions soroban-env-common/env.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion soroban-env-common/src/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub const ENV_META_V0_SECTION_NAME: &str = "contractenvmetav0";

soroban_env_macros::generate_env_meta_consts!(
ledger_protocol_version: 20,
pre_release_version: 53,
pre_release_version: 54,
);

pub fn get_ledger_protocol_version(interface_version: u64) -> u32 {
Expand Down
67 changes: 66 additions & 1 deletion soroban-env-macros/src/call_macro_with_all_host_functions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use itertools::iproduct;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use std::fs::File;
use std::{
collections::{hash_map::Entry, HashMap},
fs::File,
iter,
};
use syn::{Error, LitStr};

use serde::{Deserialize, Serialize};
Expand All @@ -25,6 +30,66 @@ pub fn generate(file_lit: LitStr) -> Result<TokenStream, Error> {
)
})?;

let mut export_names = HashMap::<String, String>::new();
for m in root.modules.iter() {
// We expect each module in the env interface to label its function
// export names according to a simple scheme: _ 0-9 a-z A-Z.
let exp_chars = iter::once('_')
.chain('0'..='9')
.chain('a'..='z')
.chain('A'..='Z')
.map(|ch| ch.to_string())
.collect::<Vec<String>>();

// This forms the sequence of 1-char names above, followed by the 2-char
// names formed by the cartesian product of that sequence with itself;
// enough to cover 4032 functions per module, far more than we'll ever
// have.
let max_names = exp_chars.len() + (exp_chars.len() * exp_chars.len());
let expected_fn_export_names = exp_chars
.iter()
.map(|x| x.to_owned())
.chain(iproduct!(exp_chars.iter(), exp_chars.iter()).map(|(a, b)| a.to_owned() + b));

if m.functions.len() > max_names {
return Err(Error::new(
file_lit.span(),
format!(
"too many functions in module '{}' in '{}': have {}, limit is {}",
m.name,
file_str,
m.functions.len(),
max_names
),
));
}

for (f, expected) in m.functions.iter().zip(expected_fn_export_names) {
let path_name = format!("{}.{}", m.name, f.name);
let export_name = format!("{}.{}", m.export, f.export);

if f.export != expected {
return Err(Error::new(
file_lit.span(),
format!("unexpected host function export-name in '{file_str}': {path_name} uses '{}' but expected '{}'", f.export, expected),
));
}

match export_names.entry(export_name.clone()) {
Entry::Occupied(existing) => {
let existing_name = existing.get();
return Err(Error::new(
file_lit.span(),
format!("duplicate host function export-name in '{file_str}': '{export_name}' used by both '{path_name}' and '{existing_name}'"),
));
}
Entry::Vacant(v) => {
v.insert(path_name);
}
}
}
}

// Build the 'mod' sections.
let modules = root.modules.iter().map(|m| {
let name = format_ident!("{}", &m.name);
Expand Down
Binary file modified soroban-test-wasms/wasm-workspace/opt/auth_test_contract.wasm
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_add_f32.wasm
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_add_i32.wasm
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_alloc.wasm
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_complex.wasm
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_contract_data.wasm
Binary file not shown.
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_err.wasm
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_fannkuch.wasm
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_fib.wasm
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_hostile.wasm
Binary file not shown.
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_linear_memory.wasm
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified soroban-test-wasms/wasm-workspace/opt/example_vec.wasm
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit db2e682

Please sign in to comment.