Skip to content

fix(#48): enforce key/value size bounds explicitly with KeyValueLimits - #66

Merged
s2x merged 1 commit into
masterfrom
fix/issue-48-key-value-size-bounds
Jul 4, 2026
Merged

fix(#48): enforce key/value size bounds explicitly with KeyValueLimits#66
s2x merged 1 commit into
masterfrom
fix/issue-48-key-value-size-bounds

Conversation

@s2x

@s2x s2x commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #48

Summary

FoundationDB's libfdb_c C API declares its length parameters as 32-bit C int. PHP strlen() returns a 64-bit integer. Neither the FoundationDB key limit (10 KB), the value limit (100 KB) nor the FFI 32-bit safety bound (2^31 - 1) were being checked at the PHP trust boundary before the FFI call.

This PR introduces src/KeyValueLimits and wires it into every FFI surface that takes a length argument:

  • Transaction/ReadTransaction writes, reads, range queries, conflict ranges
  • RangeResult (range iteration)
  • Database/Transaction option setters
  • NetworkOptions setOption
  • Database::openTenant, AdminClient tenant/server identifiers
  • rebootWorker (direct FFI call)

Each call site now gets an eager \InvalidArgumentException with the offending length at the offending line, instead of an opaque FDBException code 2102/2103 at commit time. transact() does not retry guard rejections — they are programmer errors, not transient conflicts.

Tests

  • New tests/Unit/KeyValueLimitValidationTest (28 tests, 39 assertions): accepted and rejected boundaries, FFI guard constant, named-policy message wording, data-provider coverage across the validator family.
  • Augmented tests/Integration/KeyValueLimitTest: fail-at-call-site behaviour for set/clear/clearRange/atomicOp/get/getRange, recovery after guard rejection, exact-boundary success on a live FDB cluster (key/value at the limit, clearRange with both endpoints at the limit, getRangeStartsWith with a 10 KB prefix).

Documentation

  • CHANGELOG.md entry under Unreleased / Fixed
  • docs/transactions.md new "Key / Value Size Limits" section with the limit table and on-call-site behaviour
  • docs/atomic-operations.md "Size Limits" section for atomic ops
  • docs/error-handling.md extended InvalidArgumentException entry

CI Status

  • composer lint: PHPCS OK, Rector OK, PHPStan OK
  • composer test:unit: 367 tests, 693 assertions, all pass

FoundationDB length parameters in libfdb_c are 32-bit C int while PHP
strlen() returns 64-bit, and FDB also enforces hard key (10 KB) and value
(100 KB) limits — neither boundary was being checked at the PHP trust
boundary before the FFI call.

Add src/KeyValueLimits and wire it into every FFI surface that takes a
length argument (Transaction/ReadTransaction writes, reads, range queries,
conflict ranges, option setters, RangeResult, AdminClient tenant/server,
Database tenant-name, NetworkOptions, Database setOption). Each call site
now gets an eager \\InvalidArgumentException with the offending length
at the offending line, instead of an opaque FDBException 2102/2103 at
commit time. Also rejects any byte string exceeding the 32-bit FFI
safety bound (2^31-1) so a > 2 GiB payload cannot silently truncate
across the FFI boundary.

The transaction-size aggregate (code 2101) is still reported by libfdb_c
on commit; transact() does not retry guard rejections since they are
programmer errors, not transient conflicts.

- Add tests/Unit/KeyValueLimitValidationTest covering accepted and
  rejected boundaries, the FFI guard constant, and the named-policy
  message wording.
- Augment tests/Integration/KeyValueLimitTest to prove the new
  fail-at-call-site behaviour (no opaque commit error, transactions
  recover after guard rejection) and to retain the existing accepted-
  size and transaction-aggregate coverage.
- Document the limits in docs/transactions.md (#key--value-size-limits),
  docs/atomic-operations.md (#size-limits), and docs/error-handling.md.
- CHANGELOG entry under Unreleased / Fixed.
- composer lint / composer test:unit both stay green.
@s2x
s2x merged commit 0ceefbc into master Jul 4, 2026
6 checks passed
@s2x
s2x deleted the fix/issue-48-key-value-size-bounds branch July 4, 2026 13:01
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.

[Security] Length arguments truncate to 32-bit at the FFI boundary; missing size bounds checks

1 participant