Skip to content

input validation 3 #662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9908d21
Debug failing tests iterator
pinosu Mar 26, 2025
bc95309
Add workflow
pinosu Mar 26, 2025
0243050
Add lib_test.go
pinosu Mar 26, 2025
179d142
Add lib_libwasmvm_test.go
pinosu Mar 26, 2025
743a26c
Fix test TestStoreCodeStress
pinosu Mar 26, 2025
cf6d253
Add memory_test.go
pinosu Mar 27, 2025
b1da814
Add sleep after runtime.GC() to allow GC to complete
pinosu Mar 27, 2025
ba7adb6
Fix tests
pinosu Mar 27, 2025
af326ba
Fix lint errors
pinosu Mar 27, 2025
af42e5f
yeah I should have mentioned that the heinous input validation issues…
faddat Apr 27, 2025
2eca366
run the tests right
faddat Apr 27, 2025
bf3dcb8
update rust version
faddat Apr 27, 2025
fb04911
use strip_prefix method
faddat Apr 27, 2025
38004bd
always use latest rustr
faddat Apr 27, 2025
0686a57
update circleci config
faddat Apr 27, 2025
c016094
test a change
faddat Apr 27, 2025
910e2a4
delete cargo deny action
faddat Apr 27, 2025
937120d
update tests to match updated rust
faddat Apr 27, 2025
8779553
remove typo checker because it's worse than useless
faddat Apr 27, 2025
ae3ea24
Merge remote-tracking branch 'origin/debug_failing_tests_iterator' in…
faddat Apr 27, 2025
9781a57
all tests including iterator pass.
faddat Apr 27, 2025
899c8ce
small test cleanups
faddat Apr 27, 2025
74b81c5
Update Bech32 dependency and enhance address validation in API
faddat Apr 27, 2025
a15aac6
improve tests
faddat Apr 27, 2025
71538be
complete eip-55
faddat Apr 27, 2025
ae52130
lint
faddat Apr 27, 2025
9502c47
add new tests
faddat Apr 28, 2025
225b143
fix failing tests from upgrade to wasmer v6
faddat Apr 28, 2025
e83e9dd
update failing tests
faddat Apr 28, 2025
75aa34b
update tests and fix Makefile
faddat Apr 28, 2025
62bac92
further fix test running...
faddat Apr 28, 2025
e39d1bf
enhance memory testing
faddat Apr 28, 2025
2169f06
update deps
faddat Apr 28, 2025
7573afa
build
faddat Apr 28, 2025
ad7770e
final cleanup (hopefully)
faddat Apr 29, 2025
1426818
fix remaining tests
faddat Apr 29, 2025
cea1539
return to mainline cw
faddat Apr 29, 2025
6f706d4
update module version to v3 and implement IBC2 packet timeout functio…
faddat Apr 29, 2025
f1891c1
tidy
faddat Apr 29, 2025
a51b591
fix path issue
faddat Apr 29, 2025
54b2218
tidy
faddat Apr 29, 2025
a277a0b
remove unused function
faddat Apr 29, 2025
6aa7479
remove test invalidation
faddat May 4, 2025
d2dacd1
update pr
faddat May 7, 2025
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
28 changes: 14 additions & 14 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
# All checks on the codebase that can run in parallel to build_shared_library
libwasmvm_sanity:
docker:
- image: cimg/rust:1.81.0
- image: cimg/rust:1.86.0
steps:
- checkout
- run:
Expand All @@ -18,8 +18,8 @@ jobs:
command: rustup component add rustfmt
- restore_cache:
keys:
- cargocache-v3-libwasmvm_sanity-rust:1.81.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cargocache-v3-libwasmvm_sanity-rust:1.81.0-
- cargocache-v3-libwasmvm_sanity-rust:1.86.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cargocache-v3-libwasmvm_sanity-rust:1.86.0-
- run:
name: Ensure libwasmvm/bindings.h is up-to-date
working_directory: libwasmvm
Expand Down Expand Up @@ -62,7 +62,7 @@ jobs:
- libwasmvm/target/release/.fingerprint
- libwasmvm/target/release/build
- libwasmvm/target/release/deps
key: cargocache-v3-libwasmvm_sanity-rust:1.81.0-{{ checksum "libwasmvm/Cargo.lock" }}
key: cargocache-v3-libwasmvm_sanity-rust:1.86.0-{{ checksum "libwasmvm/Cargo.lock" }}

libwasmvm_clippy:
parameters:
Expand Down Expand Up @@ -113,15 +113,15 @@ jobs:
command: |
set -o errexit
curl -sS --output rustup-init.exe https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe
./rustup-init.exe --no-modify-path --profile minimal --default-toolchain 1.81.0 -y
./rustup-init.exe --no-modify-path --profile minimal --default-toolchain 1.86.0 -y
echo 'export PATH="$PATH;$USERPROFILE/.cargo/bin"' >> "$BASH_ENV"
- run:
name: Show Rust version information
command: rustc --version; cargo --version; rustup --version
- restore_cache:
keys:
- cachev4-libwasmvm_sanity_windows-rust:1.81.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cachev4-libwasmvm_sanity_windows-rust:1.81.0-
- cachev4-libwasmvm_sanity_windows-rust:1.86.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cachev4-libwasmvm_sanity_windows-rust:1.86.0-
- run:
name: Run unit tests
working_directory: libwasmvm
Expand All @@ -133,13 +133,13 @@ jobs:
- libwasmvm/target/debug/.fingerprint
- libwasmvm/target/debug/build
- libwasmvm/target/debug/deps
key: cachev4-libwasmvm_sanity_windows-rust:1.81.0-{{ checksum "libwasmvm/Cargo.lock" }}
key: cachev4-libwasmvm_sanity_windows-rust:1.86.0-{{ checksum "libwasmvm/Cargo.lock" }}

libwasmvm_audit:
docker:
# The audit tool might use a more modern Rust version than the build jobs. See
# "Tooling Rust compiler" in docs/COMPILER_VERSIONS.md
- image: cimg/rust:1.81.0
- image: cimg/rust:1.86.0
steps:
- checkout
- run:
Expand All @@ -152,8 +152,8 @@ jobs:
command: rustc --version; cargo --version; rustup --version
- restore_cache:
keys:
- v3-libwasmvm_audit-rust:1.81.0-{{ checksum "libwasmvm/Cargo.lock" }}
- v3-libwasmvm_audit-rust:1.81.0-
- v3-libwasmvm_audit-rust:1.86.0-{{ checksum "libwasmvm/Cargo.lock" }}
- v3-libwasmvm_audit-rust:1.86.0-
- run:
name: Install cargo-audit
command: cargo install --debug cargo-audit --version 0.21.0 --locked
Expand All @@ -164,7 +164,7 @@ jobs:
- save_cache:
paths:
- ~/.cargo/registry
key: v3-libwasmvm_audit-rust:1.81.0-{{ checksum "libwasmvm/Cargo.lock" }}
key: v3-libwasmvm_audit-rust:1.86.0-{{ checksum "libwasmvm/Cargo.lock" }}

format-go:
docker:
Expand Down Expand Up @@ -294,7 +294,7 @@ jobs:
- libwasmvm/target/release/.fingerprint
- libwasmvm/target/release/build
- libwasmvm/target/release/deps
key: cargocache-v3-build_shared_library-rust:1.81.0-{{ checksum "libwasmvm/Cargo.lock" }}
key: cargocache-v3-build_shared_library-rust:1.86.0-{{ checksum "libwasmvm/Cargo.lock" }}

# Test the Go project and run benchmarks
wasmvm_test:
Expand Down Expand Up @@ -456,7 +456,7 @@ workflows:
matrix:
parameters:
# Run with MSRV and some modern stable Rust
rust-version: ["1.81.0", "1.82.0"]
rust-version: ["1.86.0", "1.86.0"]
- libwasmvm_audit
- format-go
- wasmvm_no_cgo
Expand Down
6 changes: 6 additions & 0 deletions .cursor/rules/project-description.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
description:
globs:
alwaysApply: true
---
This project is written in go, c and rust, and it serves as the interop layer between cosmwasm's vm and cosmos blockchains written in go. Please be attentive to the multi-lingual nature of the project when working with it.
27 changes: 27 additions & 0 deletions .github/workflows/bat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
on: [push, pull_request]
name: Test
jobs:
test:
strategy:
matrix:
go-version: [1.24.x]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- run: make test
build:
strategy:
matrix:
go-version: [1.24.x]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- run: make build
38 changes: 38 additions & 0 deletions .github/workflows/cargo-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Cargo Audit

on:
push:
branches: [main]
paths:
- "**/Cargo.toml"
- "**/Cargo.lock"
- ".github/workflows/cargo-audit.yml"
pull_request:
paths:
- "**/Cargo.toml"
- "**/Cargo.lock"
- ".github/workflows/cargo-audit.yml"
schedule:
- cron: "0 0 * * 0" # Run weekly on Sundays at midnight

jobs:
cargo-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Install cargo-audit
run: cargo install cargo-audit

- name: Run cargo audit
working-directory: ./libwasmvm
run: cargo audit
continue-on-error: ${{ github.event_name == 'schedule' }} # Don't fail scheduled runs

- name: Run cargo audit with ignore unmaintained
working-directory: ./libwasmvm
run: cargo audit --ignore RUSTSEC-2024-0436 --ignore RUSTSEC-2024-0370
# These are the unmaintained crates we're already tracking in deny.toml
2 changes: 1 addition & 1 deletion .github/workflows/lint-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.23.4"
go-version: "1.24"
cache: false
- name: golangci-lint
uses: golangci/golangci-lint-action@v7
Expand Down
19 changes: 0 additions & 19 deletions .github/workflows/typo-check.yml

This file was deleted.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ build-go:
.PHONY: test
test:
# Use package list mode to include all subdirectores. The -count=1 turns off caching.
RUST_BACKTRACE=1 go test -v -count=1 ./...
CGO_ENABLED=1 RUST_BACKTRACE=1 go test -v -count=1 ./...

.PHONY: test-safety
test-safety:
Expand Down
7 changes: 3 additions & 4 deletions internal/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestValidateAddressFailure(t *testing.T) {

// if the human address is larger than 32 bytes, this will lead to an error in the go side
longName := "long123456789012345678901234567890long"
msg := []byte(`{"verifier": "` + longName + `", "beneficiary": "bob"}`)
msg := []byte(`{"verifier": "` + longName + `", "beneficiary": "` + SafeBech32Address("bob") + `"}`)

// make sure the call doesn't error, but we get a JSON-encoded error result from ContractResult
igasMeter := types.GasMeter(gasMeter)
Expand All @@ -41,7 +41,6 @@ func TestValidateAddressFailure(t *testing.T) {
require.NoError(t, err)

// ensure the error message is what we expect
require.Nil(t, result.Ok)
// with this error
require.Equal(t, "Generic error: addr_validate errored: human encoding too long", result.Err)
require.NotNil(t, result.Err)
require.Contains(t, result.Err, "addr_validate errored: Invalid Bech32 address")
}
88 changes: 86 additions & 2 deletions internal/api/bindings.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Licensed under Apache-2.0. Copyright see https://github.com/CosmWasm/wasmvm/blob/main/NOTICE. */

/* Generated with cbindgen:0.27.0 */
/* Generated with cbindgen:0.28.0 */

/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */

Expand All @@ -9,6 +9,8 @@
#include <stdint.h>
#include <stdlib.h>

#define MAX_ADDRESS_LENGTH 256

enum ErrnoValue {
ErrnoValue_Success = 0,
ErrnoValue_Other = 1,
Expand Down Expand Up @@ -53,6 +55,12 @@ enum GoError {
};
typedef int32_t GoError;

/**
* A safety wrapper around UnmanagedVector that prevents double consumption
* of the same vector and adds additional safety checks
*/
typedef struct SafeUnmanagedVector SafeUnmanagedVector;

typedef struct cache_t {

} cache_t;
Expand Down Expand Up @@ -171,7 +179,7 @@ typedef struct ByteSliceView {
* let mut mutable: Vec<u8> = input.consume().unwrap_or_default();
* assert_eq!(mutable, vec![0xAA]);
*
* // `input` is now gone and we can do everything we want to `mutable`,
* // `input` is now gone and we cam do everything we want to `mutable`,
* // including operations that reallocate the underlying data.
*
* mutable.push(0xBB);
Expand Down Expand Up @@ -425,6 +433,15 @@ struct UnmanagedVector store_code(struct cache_t *cache,
bool persist,
struct UnmanagedVector *error_msg);

/**
* A safer version of store_code that returns a SafeUnmanagedVector to prevent double-free issues
*/
struct SafeUnmanagedVector *store_code_safe(struct cache_t *cache,
struct ByteSliceView wasm,
bool checked,
bool persist,
struct UnmanagedVector *error_msg);

void remove_wasm(struct cache_t *cache,
struct ByteSliceView checksum,
struct UnmanagedVector *error_msg);
Expand All @@ -433,6 +450,13 @@ struct UnmanagedVector load_wasm(struct cache_t *cache,
struct ByteSliceView checksum,
struct UnmanagedVector *error_msg);

/**
* A safer version of load_wasm that returns a SafeUnmanagedVector to prevent double-free issues
*/
struct SafeUnmanagedVector *load_wasm_safe(struct cache_t *cache,
struct ByteSliceView checksum,
struct UnmanagedVector *error_msg);

void pin(struct cache_t *cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg);

void unpin(struct cache_t *cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg);
Expand Down Expand Up @@ -664,8 +688,68 @@ struct UnmanagedVector ibc2_packet_timeout(struct cache_t *cache,

struct UnmanagedVector new_unmanaged_vector(bool nil, const uint8_t *ptr, uintptr_t length);

/**
* Creates a new SafeUnmanagedVector from provided data
* This function provides a safer alternative to new_unmanaged_vector
* by returning a reference to a heap-allocated SafeUnmanagedVector
* which includes consumption tracking.
*
* # Safety
*
* The returned pointer must be freed exactly once using destroy_safe_unmanaged_vector.
* The caller is responsible for ensuring this happens.
*/
struct SafeUnmanagedVector *new_safe_unmanaged_vector(bool nil,
const uint8_t *ptr,
uintptr_t length);

/**
* Safely destroys a SafeUnmanagedVector, handling consumption tracking
* to prevent double-free issues.
*
* # Safety
*
* The pointer must have been created with new_safe_unmanaged_vector.
* After this call, the pointer must not be used again.
*/
void destroy_safe_unmanaged_vector(struct SafeUnmanagedVector *v);

void destroy_unmanaged_vector(struct UnmanagedVector v);

/**
* Checks if a SafeUnmanagedVector contains a None value
*
* # Safety
*
* The pointer must point to a valid SafeUnmanagedVector created with
* new_safe_unmanaged_vector or a related function.
*/
bool safe_unmanaged_vector_is_none(const struct SafeUnmanagedVector *v);

/**
* Gets the length of a SafeUnmanagedVector
* Returns 0 if the vector is None or has been consumed
*
* # Safety
*
* The pointer must point to a valid SafeUnmanagedVector created with
* new_safe_unmanaged_vector or a related function.
*/
uintptr_t safe_unmanaged_vector_length(const struct SafeUnmanagedVector *v);

/**
* Copies the content of a SafeUnmanagedVector into a newly allocated Go byte slice
* Returns a pointer to the data and its length, which must be freed by Go
*
* # Safety
*
* The pointer must point to a valid SafeUnmanagedVector created with
* new_safe_unmanaged_vector or a related function.
*/
bool safe_unmanaged_vector_to_bytes(struct SafeUnmanagedVector *v,
uint8_t **output_data,
uintptr_t *output_len);

/**
* Returns a version number of this library as a C string.
*
Expand Down
Loading
Loading