Skip to content

Commit 4b45b4e

Browse files
authored
Error during contract build without overflow checks (#2367)
1 parent daac568 commit 4b45b4e

File tree

3 files changed

+142
-161
lines changed

3 files changed

+142
-161
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ predicates = "3.1.2"
120120
testcontainers = { version = "0.26.0" }
121121
httpmock = "0.7.0"
122122

123+
[profile.release]
124+
overflow-checks = true
125+
123126
[profile.test-wasms]
124127
inherits = "release"
125128
opt-level = "z"

cmd/crates/soroban-test/tests/it/build.rs

Lines changed: 116 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ fn build_with_metadata_rewrite() {
134134
let sandbox = TestEnv::default();
135135
let outdir = sandbox.dir().join("out");
136136
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
137-
let fixture_path = cargo_dir.join("tests/fixtures/workspace/contracts/add");
137+
let fixture_path = cargo_dir.join("tests/fixtures/workspace");
138138
let temp = TempDir::new().unwrap();
139139
let dir_path = temp.path();
140140
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
141-
let dir_path = dir_path.join("add");
141+
let dir_path = dir_path.join("workspace").join("contracts").join("add");
142142

143143
sandbox
144144
.new_assert_cmd("contract")
@@ -190,11 +190,11 @@ fn build_with_metadata_diff_dir() {
190190
let outdir1 = sandbox.dir().join("out-1");
191191
let outdir2 = sandbox.dir().join("out-2");
192192
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
193-
let fixture_path = cargo_dir.join("tests/fixtures/workspace/contracts/add");
193+
let fixture_path = cargo_dir.join("tests/fixtures/workspace");
194194
let temp = TempDir::new().unwrap();
195195
let dir_path = temp.path();
196196
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
197-
let dir_path = dir_path.join("add");
197+
let dir_path = dir_path.join("workspace").join("contracts").join("add");
198198

199199
sandbox
200200
.new_assert_cmd("contract")
@@ -402,45 +402,70 @@ fn remap_absolute_paths() {
402402
}
403403

404404
#[test]
405-
fn build_warns_when_overflow_checks_missing() {
405+
fn build_no_error_for_workspace() {
406406
let sandbox = TestEnv::default();
407+
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
408+
let fixture_path = cargo_dir.join("tests/fixtures/workspace");
407409
let temp = TempDir::new().unwrap();
408410
let dir_path = temp.path();
411+
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
412+
let dir_path = dir_path.join("workspace");
409413

410-
// Create a workspace without overflow-checks in profile
411-
std::fs::write(
412-
dir_path.join("Cargo.toml"),
413-
r#"
414-
[workspace]
415-
resolver = "2"
416-
members = ["contract"]
414+
// By default, workspace TOML has overflow-checks = true
417415

418-
[profile.release]
419-
opt-level = "z"
420-
"#,
421-
)
422-
.unwrap();
416+
sandbox
417+
.new_assert_cmd("contract")
418+
.current_dir(&dir_path)
419+
.arg("build")
420+
.assert()
421+
.success();
422+
}
423423

424-
std::fs::create_dir_all(dir_path.join("contract/src")).unwrap();
425-
std::fs::write(
426-
dir_path.join("contract/Cargo.toml"),
427-
r#"
428-
[package]
429-
name = "test-contract"
430-
version = "0.1.0"
431-
edition = "2021"
424+
#[test]
425+
fn build_no_error_for_package() {
426+
let sandbox = TestEnv::default();
427+
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
428+
let fixture_path = cargo_dir.join("tests/fixtures/workspace/contracts/add/add2");
429+
let temp = TempDir::new().unwrap();
430+
let dir_path = temp.path();
431+
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
432+
let dir_path = dir_path.join("add2");
432433

433-
[lib]
434-
crate-type = ["cdylib"]
435-
"#,
436-
)
437-
.unwrap();
438-
std::fs::write(dir_path.join("contract/src/lib.rs"), "").unwrap();
434+
// By default, this TOML does not specify overflow-checks, add it
435+
let cargo_toml_path = dir_path.join("Cargo.toml");
436+
let cargo_toml_path_content = std::fs::read_to_string(&cargo_toml_path).unwrap();
437+
let modified_cargo_toml_content =
438+
format!("{cargo_toml_path_content}\n[profile.release]\noverflow-checks = true\n",);
439+
std::fs::write(&cargo_toml_path, modified_cargo_toml_content).unwrap();
439440

440-
// Build will fail (no panic handler), but warning should appear first
441441
sandbox
442442
.new_assert_cmd("contract")
443-
.current_dir(dir_path)
443+
.current_dir(&dir_path)
444+
.arg("build")
445+
.assert()
446+
.success();
447+
}
448+
449+
#[test]
450+
fn build_errors_when_overflow_checks_false() {
451+
let sandbox = TestEnv::default();
452+
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
453+
let fixture_path = cargo_dir.join("tests/fixtures/workspace");
454+
let temp = TempDir::new().unwrap();
455+
let dir_path = temp.path();
456+
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
457+
let dir_path = dir_path.join("workspace");
458+
459+
// Replace overflow-checks = true with false in workspace Cargo.toml
460+
let cargo_toml_path = dir_path.join("Cargo.toml");
461+
let cargo_toml_content = std::fs::read_to_string(&cargo_toml_path).unwrap();
462+
let modified_content =
463+
cargo_toml_content.replace("overflow-checks = true", "overflow-checks = false");
464+
std::fs::write(&cargo_toml_path, modified_content).unwrap();
465+
466+
sandbox
467+
.new_assert_cmd("contract")
468+
.current_dir(&dir_path)
444469
.arg("build")
445470
.assert()
446471
.failure()
@@ -450,157 +475,102 @@ crate-type = ["cdylib"]
450475
}
451476

452477
#[test]
453-
fn build_no_warning_when_overflow_checks_enabled() {
478+
fn build_errors_when_overflow_checks_missing() {
454479
let sandbox = TestEnv::default();
480+
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
481+
let fixture_path = cargo_dir.join("tests/fixtures/workspace");
455482
let temp = TempDir::new().unwrap();
456483
let dir_path = temp.path();
484+
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
485+
let dir_path = dir_path.join("workspace");
457486

458-
// Create a workspace with overflow-checks = true
459-
std::fs::write(
460-
dir_path.join("Cargo.toml"),
461-
r#"
462-
[workspace]
463-
resolver = "2"
464-
members = ["contract"]
465-
466-
[profile.release]
467-
opt-level = "z"
468-
overflow-checks = true
469-
"#,
470-
)
471-
.unwrap();
472-
473-
std::fs::create_dir_all(dir_path.join("contract/src")).unwrap();
474-
std::fs::write(
475-
dir_path.join("contract/Cargo.toml"),
476-
r#"
477-
[package]
478-
name = "test-contract"
479-
version = "0.1.0"
480-
edition = "2021"
481-
482-
[lib]
483-
crate-type = ["cdylib"]
484-
"#,
485-
)
486-
.unwrap();
487-
std::fs::write(dir_path.join("contract/src/lib.rs"), "").unwrap();
487+
// Remove overflow-checks line from workspace Cargo.toml
488+
let cargo_toml_path = dir_path.join("Cargo.toml");
489+
let cargo_toml_content = std::fs::read_to_string(&cargo_toml_path).unwrap();
490+
let modified_content = cargo_toml_content.replace("overflow-checks = true\n", "");
491+
std::fs::write(&cargo_toml_path, modified_content).unwrap();
488492

489-
// Build will fail (no panic handler), but no overflow warning should appear
490493
sandbox
491494
.new_assert_cmd("contract")
492-
.current_dir(dir_path)
495+
.current_dir(&dir_path)
493496
.arg("build")
494497
.assert()
495498
.failure()
496-
.stderr(predicate::str::contains("overflow-checks").not());
499+
.stderr(predicate::str::contains(
500+
"`overflow-checks` is not enabled for profile `release`",
501+
));
497502
}
498503

499504
#[test]
500-
fn build_no_warning_when_profile_inherits_overflow_checks() {
505+
fn build_errors_when_package_overflow_checks_missing() {
501506
let sandbox = TestEnv::default();
507+
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
508+
let fixture_path = cargo_dir.join("tests/fixtures/workspace/contracts/add/add2");
502509
let temp = TempDir::new().unwrap();
503510
let dir_path = temp.path();
511+
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
512+
let dir_path = dir_path.join("add2");
504513

505-
// Create a workspace where custom profile inherits from release with overflow-checks
506-
std::fs::write(
507-
dir_path.join("Cargo.toml"),
508-
r#"
509-
[workspace]
510-
resolver = "2"
511-
members = ["contract"]
512-
513-
[profile.release]
514-
opt-level = "z"
515-
overflow-checks = true
516-
517-
[profile.custom]
518-
inherits = "release"
519-
"#,
520-
)
521-
.unwrap();
522-
523-
std::fs::create_dir_all(dir_path.join("contract/src")).unwrap();
524-
std::fs::write(
525-
dir_path.join("contract/Cargo.toml"),
526-
r#"
527-
[package]
528-
name = "test-contract"
529-
version = "0.1.0"
530-
edition = "2021"
531-
532-
[lib]
533-
crate-type = ["cdylib"]
534-
"#,
535-
)
536-
.unwrap();
537-
std::fs::write(dir_path.join("contract/src/lib.rs"), "").unwrap();
514+
// By default, this TOML does not specify overflow-checks
538515

539-
// Build with custom profile - no warning should appear
540516
sandbox
541517
.new_assert_cmd("contract")
542-
.current_dir(dir_path)
518+
.current_dir(&dir_path)
543519
.arg("build")
544-
.arg("--profile=custom")
545520
.assert()
546521
.failure()
547-
.stderr(predicate::str::contains("overflow-checks").not());
522+
.stderr(predicate::str::contains(
523+
"`overflow-checks` is not enabled for profile `release`",
524+
));
548525
}
549526

550527
#[test]
551-
fn build_warns_when_inherited_profile_missing_overflow_checks() {
528+
fn build_errors_when_overflow_check_only_applied_to_members() {
552529
let sandbox = TestEnv::default();
530+
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
531+
let fixture_path = cargo_dir.join("tests/fixtures/workspace");
553532
let temp = TempDir::new().unwrap();
554533
let dir_path = temp.path();
534+
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
535+
let dir_path = dir_path.join("workspace");
536+
537+
// Remove overflow-checks line from workspace Cargo.toml
538+
let cargo_toml_path = dir_path.join("Cargo.toml");
539+
let cargo_toml_content = std::fs::read_to_string(&cargo_toml_path).unwrap();
540+
let modified_content = cargo_toml_content.replace("overflow-checks = true\n", "");
541+
std::fs::write(&cargo_toml_path, modified_content).unwrap();
542+
543+
// Add overflow-checks = true to "add" member
544+
let member_cargo_toml_path = dir_path.join("contracts").join("add").join("Cargo.toml");
545+
let member_cargo_toml_content = std::fs::read_to_string(&member_cargo_toml_path).unwrap();
546+
let modified_member_content =
547+
format!("{member_cargo_toml_content}\n[profile.release]\noverflow-checks = true\n",);
548+
std::fs::write(&member_cargo_toml_path, modified_member_content).unwrap();
549+
550+
// Add overflow-checks = true to "add2" member
551+
let member_2_cargo_toml_path = dir_path
552+
.join("contracts")
553+
.join("add")
554+
.join("add2")
555+
.join("Cargo.toml");
556+
let member_2_cargo_toml_content = std::fs::read_to_string(&member_2_cargo_toml_path).unwrap();
557+
let modified_member_2_content =
558+
format!("{member_2_cargo_toml_content}\n[profile.release]\noverflow-checks = true\n",);
559+
std::fs::write(&member_2_cargo_toml_path, modified_member_2_content).unwrap();
555560

556-
// Create a workspace where custom profile inherits from release without overflow-checks
557-
std::fs::write(
558-
dir_path.join("Cargo.toml"),
559-
r#"
560-
[workspace]
561-
resolver = "2"
562-
members = ["contract"]
563-
564-
[profile.release]
565-
opt-level = "z"
566-
567-
[profile.custom]
568-
inherits = "release"
569-
"#,
570-
)
571-
.unwrap();
572-
573-
std::fs::create_dir_all(dir_path.join("contract/src")).unwrap();
574-
std::fs::write(
575-
dir_path.join("contract/Cargo.toml"),
576-
r#"
577-
[package]
578-
name = "test-contract"
579-
version = "0.1.0"
580-
edition = "2021"
581-
582-
[lib]
583-
crate-type = ["cdylib"]
584-
"#,
585-
)
586-
.unwrap();
587-
std::fs::write(dir_path.join("contract/src/lib.rs"), "").unwrap();
588-
589-
// Build with custom profile - warning should appear
590561
sandbox
591562
.new_assert_cmd("contract")
592-
.current_dir(dir_path)
563+
.current_dir(&dir_path)
593564
.arg("build")
594-
.arg("--profile=custom")
595565
.assert()
596566
.failure()
597567
.stderr(predicate::str::contains(
598-
"`overflow-checks` is not enabled for profile `custom`",
568+
"`overflow-checks` is not enabled for profile `release`",
599569
));
600570
}
601571

602572
#[test]
603-
fn build_no_warning_with_print_commands_only() {
573+
fn build_no_error_with_print_commands_only() {
604574
let sandbox = TestEnv::default();
605575
let temp = TempDir::new().unwrap();
606576
let dir_path = temp.path();
@@ -651,11 +621,11 @@ fn build_always_injects_cli_version() {
651621
let sandbox = TestEnv::default();
652622
let outdir = sandbox.dir().join("out");
653623
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
654-
let fixture_path = cargo_dir.join("tests/fixtures/workspace/contracts/add");
624+
let fixture_path = cargo_dir.join("tests/fixtures/workspace");
655625
let temp = TempDir::new().unwrap();
656626
let dir_path = temp.path();
657627
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
658-
let dir_path = dir_path.join("add");
628+
let dir_path = dir_path.join("workspace").join("contracts").join("add");
659629

660630
// Build contract without any metadata args
661631
sandbox

0 commit comments

Comments
 (0)