Summary
CefPostDataElement.setToBytes(int size, byte[] bytes) crashes the JVM process with a silent segfault (no FATAL/DCHECK diagnostic printed at all, unlike every other crash found this session) when called with a negative size -- e.g. element.setToBytes(-1, data).
Root cause
native/CefPostDataElement_N.cpp:
Java_org_cef_network_CefPostDataElement_1N_N_1SetToBytes(JNIEnv* env, jobject obj, jlong self,
jint jsize, jbyteArray jbytes) {
...
jbyte* jbyte = env->GetByteArrayElements(jbytes, nullptr);
if (!jbyte)
return;
dataElement->SetToBytes(jsize, jbyte);
...
}
jsize is a signed jint (Java int), passed directly into CefPostDataElement::SetToBytes(), whose C++ signature takes a size_t (unsigned). A negative jsize (e.g. -1) implicitly converts to a huge unsigned value (SIZE_MAX for -1) when passed as size_t. The underlying implementation then almost certainly does something like memcpy(dest, jbyte, size) with that huge size, reading far past the end of the real (tiny) source buffer -- a classic signed/unsigned integer confusion leading to a buffer over-read and segfault.
No bounds/sign check exists on the JCEF JNI side before this value crosses into native code.
Repro
Added java/tests/junittests/MalformedInputEdgeCaseTest.java's
postDataElementSetToBytesWithNegativeSizeDoesNotThrow() (currently @Disabled with a link to this issue -- remove @Disabled to re-run it, ideally under a hard external timeout wrapper since this crash is silent and un-diagnosable from output alone):
CefPostDataElement element = CefPostDataElement.create();
byte[] data = {1, 2, 3};
element.setToBytes(-1, data); // crashes, no diagnostic printed
Confirmed via an isolated --select-method run: the process aborts (SIGTRAP/core dump) with zero FATAL/DCHECK/error output of any kind -- distinct from every other crash found this session (issues #9, #16), all of which at least print a FATAL: line before aborting. This one is silent, consistent with a raw out-of-bounds memory access rather than a deliberate assertion.
Impact
A negative (or otherwise invalid, e.g. larger than the actual array length -- untested here, but worth checking too) size argument to setToBytes() is exactly the kind of input a real embedding application could pass by accident (an off-by-one, an unvalidated computed length, etc.), and the result is an unrecoverable process crash with no diagnostic to even explain what happened. This is a real robustness/safety gap, not just a coverage-tooling artifact.
Fix sketch (not implemented here)
Validate jsize >= 0 (and ideally jsize <= <actual jbytes array length>) in the JNI shim before calling dataElement->SetToBytes(), returning early or throwing a Java exception for an invalid value instead of passing it straight through.
Found via
This fork's coverage-expansion effort (tracked in #5), specifically a "bad-path"/malformed-input test-writing round per the user's explicit direction ("continue with a big bang bad path test write") targeting numeric/size-mismatch edge cases across already-covered APIs.
Summary
CefPostDataElement.setToBytes(int size, byte[] bytes)crashes the JVM process with a silent segfault (noFATAL/DCHECKdiagnostic printed at all, unlike every other crash found this session) when called with a negativesize-- e.g.element.setToBytes(-1, data).Root cause
native/CefPostDataElement_N.cpp:jsizeis a signedjint(Javaint), passed directly intoCefPostDataElement::SetToBytes(), whose C++ signature takes asize_t(unsigned). A negativejsize(e.g.-1) implicitly converts to a huge unsigned value (SIZE_MAXfor-1) when passed assize_t. The underlying implementation then almost certainly does something likememcpy(dest, jbyte, size)with that huge size, reading far past the end of the real (tiny) source buffer -- a classic signed/unsigned integer confusion leading to a buffer over-read and segfault.No bounds/sign check exists on the JCEF JNI side before this value crosses into native code.
Repro
Added
java/tests/junittests/MalformedInputEdgeCaseTest.java'spostDataElementSetToBytesWithNegativeSizeDoesNotThrow()(currently@Disabledwith a link to this issue -- remove@Disabledto re-run it, ideally under a hard externaltimeoutwrapper since this crash is silent and un-diagnosable from output alone):Confirmed via an isolated
--select-methodrun: the process aborts (SIGTRAP/core dump) with zeroFATAL/DCHECK/error output of any kind -- distinct from every other crash found this session (issues #9, #16), all of which at least print aFATAL:line before aborting. This one is silent, consistent with a raw out-of-bounds memory access rather than a deliberate assertion.Impact
A negative (or otherwise invalid, e.g. larger than the actual array length -- untested here, but worth checking too)
sizeargument tosetToBytes()is exactly the kind of input a real embedding application could pass by accident (an off-by-one, an unvalidated computed length, etc.), and the result is an unrecoverable process crash with no diagnostic to even explain what happened. This is a real robustness/safety gap, not just a coverage-tooling artifact.Fix sketch (not implemented here)
Validate
jsize >= 0(and ideallyjsize <= <actual jbytes array length>) in the JNI shim before callingdataElement->SetToBytes(), returning early or throwing a Java exception for an invalid value instead of passing it straight through.Found via
This fork's coverage-expansion effort (tracked in #5), specifically a "bad-path"/malformed-input test-writing round per the user's explicit direction ("continue with a big bang bad path test write") targeting numeric/size-mismatch edge cases across already-covered APIs.