Problem
src/phongo_bson_encode.c discards the boolean return of libbson append functions in several places:* Line 125, 132: bson_append_document_begin / bson_append_array_unsafe_begin for Persistable / Serializable objects
- Line 244: bson_append_document_begin for the generic object fallback
- Line 306: bson_append_array_unsafe_begin for PHP arrays serialized as BSON arrays
- Line 260 to 280 and every scalar bson_append_* call in phongo_bson_append_object: scalar appends whose return value is dropped
Per the libbson contract (see bson_append_document_begin docs), when these functions return false the child out-parameter is invalid and must not be used. libbson itself returns false when the parent buffer would grow beyond INT32_MAX (2 GiB), or when an underlying allocation fails.
The encoder currently ignores the return and unconditionally recurses into the uninitialized child, then calls bson_append_document_end on it. libbson's defensive BSON_ASSERT((bson->flags & BSON_FLAG_IN_CHILD)) then triggers abort(), killing the PHP worker.
Reproduction
Encoding an aggregate BSON document larger than INT32_MAX reliably aborts the process. PHP copy-on-write means a modest PHP graph can amplify to a very large encode (same subarray referenced N times is re-serialized N times). Minimal reproducer attached to SECBUG-4151.
Additional integrity issue
Scalar bson_append_* return values are also discarded. When the cap is reached mid-encode, subsequent scalar appends silently no-op and the truncated document is finalized without error. This can drop caller-injected fields (for example _id, or the __pclass metadata for Persistable) with no signal to the application.
Proposed fix
- Check the return of every bson_append_*_begin call. On false, raise a PHP exception (MongoDB\Driver\Exception\UnexpectedValueException or a more specific encoding exception) and abort the encode.
- Same for scalar appends whose failure would silently truncate the document.
- Optionally, add an aggregate size guard in the encoder well below BSON_MAX_SIZE so the error is surfaced early with a clearer message.
Related
- SECBUG-4151 (heap corruption / DoS via unchecked BSON append failures)