Skip to content

Check integer ranges and BytesN lengths in ContractSpec - #199

Merged
christian-rogobete merged 1 commit into
mainfrom
hardening-contract-spec-ints
Nov 4, 2026
Merged

christian-rogobete merged 1 commit into
mainfrom
hardening-contract-spec-ints

Conversation

@christian-rogobete

Copy link
Copy Markdown
Member

Fixes a defect in ContractSpec argument conversion. Before this change, nativeToXdrSCVal checked a u32 integer only for a negative sign and an i32 integer not at all. The XDR encoder kept the low 32 bits of the value, so a u32 of 4294967296 encoded as 0 and an i32 of 2147483648 as -2147483648 without an error. A BytesN parameter took a string of any length and produced an SCVal that the host rejects. An app that passed a user-supplied integer to a contract function could therefore invoke it with a wrong value. A byte string of the wrong length failed at the host.

This change:

  • Rejects a u32 or i32 integer outside its range with an InvalidArgumentException naming the value and the range.
  • Checks the byte length of a BytesN string against the declared length and rejects a mismatch with an InvalidArgumentException naming both lengths.
  • Adds boundary tests for the two integer types and for BytesN of lengths 0 and 32 with binary and multibyte strings, and names the three rules in the function's documentation.
  • Moves the TxRep entry of the CHANGELOG from the 1.17.0 section to Unreleased.

Every value inside its type and every string of the declared length converts to the same SCVal as before.

Closes #198

Fixes a defect in `ContractSpec` argument conversion. Before this
change, `nativeToXdrSCVal` checked a `u32` integer only for a negative
sign and an `i32` integer not at all. The XDR encoder kept the low 32
bits of the value, so a `u32` of 4294967296 encoded as 0 and an `i32` of
2147483648 as -2147483648 without an error. A `BytesN` parameter took a
string of any length and produced an `SCVal` that the host rejects. An
app that passed a user-supplied integer to a contract function could
therefore invoke it with a wrong value. A byte string of the wrong
length failed at the host.

This change:

- Rejects a `u32` or `i32` integer outside its range with an
  `InvalidArgumentException` naming the value and the range.
- Checks the byte length of a `BytesN` string against the declared
  length and rejects a mismatch with an `InvalidArgumentException`
  naming both lengths.
- Adds boundary tests for the two integer types and for `BytesN` of
  lengths 0 and 32 with binary and multibyte strings, and names the
  three rules in the function's documentation.
- Moves the TxRep entry of the CHANGELOG from the 1.17.0 section to
  Unreleased.

Every value inside its type and every string of the declared length
converts to the same `SCVal` as before.

Closes #198
@codecov

codecov Bot commented Nov 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.46%. Comparing base (b257e46) to head (6c1b799).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##               main     #199   +/-   ##
=========================================
  Coverage     93.46%   93.46%           
- Complexity    21603    21609    +6     
=========================================
  Files          1006     1006           
  Lines         52392    52399    +7     
=========================================
+ Hits          48967    48974    +7     
  Misses         3425     3425           
Files with missing lines Coverage Δ
...oneso/StellarSDK/Soroban/Contract/ContractSpec.php 92.46% <100.00%> (+0.16%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@christian-rogobete
christian-rogobete merged commit b55201c into main Nov 4, 2026
10 checks passed
@christian-rogobete
christian-rogobete deleted the hardening-contract-spec-ints branch November 4, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ContractSpec encodes out-of-range u32 and i32 integers as wrapped values and accepts any BytesN length

1 participant