Repository navigation
crypto: fix property attributes of X509Certificate validFromDate/validToDate - #37057
Conversation
…dToDate validFromDate and validToDate were registered with the CustomAccessorOrValue attribute mask instead of CustomAccessor, unlike every other accessor row in the prototype table. Get/put paths check the CustomAccessor bit first, so release builds behaved, but any descriptor read over the prototype (Object.getOwnPropertyDescriptor, Object.getOwnPropertyDescriptors, util.inspect with showHidden) aborted assert-enabled builds: ASSERTION FAILED: !(attributes & PropertyAttribute::CustomAccessorOrValue) JavaScriptCore/runtime/PropertyDescriptor.cpp(183) setAccessorDescriptor
|
Warning Review limit reached
Next review available in: 13 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Comment |
There was a problem hiding this comment.
LGTM — mechanical two-line attribute fix aligning validFromDate/validToDate with every sibling accessor row.
What was reviewed:
- Confirmed
CustomAccessorOrValueis a test mask (=CustomAccessor | CustomValue), not a valid stored attribute; the two changed rows now match the other ~15CustomAccessorrows in the same table. - Grepped
src/jsc/bindingsfor otherCustomAccessorOrValueuses as a stored attribute — none remain; the two hits inErrorStackTrace.cppare correct mask tests. - New tests exercise both the single-descriptor and whole-prototype-walk paths that previously asserted, plus verify the extracted getters still return correct
Datevalues on an instance.
Extended reasoning...
Overview
Two-line change in src/jsc/bindings/JSX509CertificatePrototype.cpp swapping PropertyAttribute::CustomAccessorOrValue → PropertyAttribute::CustomAccessor on the validFromDate and validToDate HashTableValue rows, plus two regression tests in test/js/node/crypto/x509.test.ts.
CustomAccessorOrValue is defined in JSC as CustomAccessor | CustomValue — a convenience mask for testing whether an attribute is either kind, not a value to set. Setting both bits is contradictory (a slot is either a custom accessor or a custom value). When getOwnPropertyDescriptor reifies the entry, it strips the CustomAccessor bit but the stray CustomValue bit survives into PropertyDescriptor::setAccessorDescriptor, which asserts !(attributes & CustomAccessorOrValue). Release builds don't crash because the get/put fast paths check the CustomAccessor bit first and never reach the assertion.
Security risks
None. This adjusts a static property-attribute flag on two read-only prototype getters. No parsing, no allocation, no user-controlled input paths are touched. The only observable effect is that debug/ASAN builds no longer abort on Object.getOwnPropertyDescriptor(X509Certificate.prototype, 'validFromDate').
Level of scrutiny
Low. This is a copy-paste-class bug where two rows used the wrong enum member while all ~15 sibling rows used the correct one. The fix is purely mechanical — make the outliers match their neighbours. There is no design decision, no new code path, and no release-build behaviour change (the CustomAccessor bit was already set before, so property lookup semantics are identical).
Other factors
- Whole-class check: I grepped
src/jsc/bindingsforCustomAccessorOrValue— the only remaining uses (ErrorStackTrace.cpp:618,634) are correct bitmask tests (attributes & CustomAccessorOrValue), so no other HashTableValue rows share this bug. - Tests: The first new test reads descriptors for the two fixed properties and their siblings
validFrom/validTo, asserting identical shape — this directly triggers the pre-fix abort and guards against divergence. The full-prototypegetOwnPropertyDescriptorswalk covers theutil.inspect(proto, {showHidden: true})case from the PR description. The second test verifies the extracted getters still function correctly on an instance (returns aDateequal to direct property access), guarding against accidentally breaking the accessor while fixing the attribute. - PR verification claims are consistent with the change: the repro aborts on main (exit 134) and passes after; adjacent x509 test files still pass.
|
CI status for build 89621: the only hard failure is test/js/node/worker_threads/worker-transfer-terminate-stress.test.ts (SIGABRT on the Debian 13 x64-asan lane). That failure is present on main as well and is unrelated to this change; it has been reported for separate triage. Every other failing file in the build is a known-flaky test that passed on retry or passed when run alone. The new x509 descriptor tests passed on all lanes, including x64-asan, which is the lane where the original assertion fired. The diff is ready for review. |
Problem
Reading a property descriptor of
X509Certificate.prototype.validFromDateor.validToDateaborts assert-enabled (debug/ASAN) builds. No certificate needed:Anything that walks descriptors hits it too:
Object.getOwnPropertyDescriptors(X509Certificate.prototype),util.inspect(proto, { showHidden: true }), test utilities that snapshot descriptors. Release builds are unaffected because get/put check theCustomAccessorbit first.Cause
The
validFromDateandvalidToDaterows inJSX509CertificatePrototypeTableValuesused the attribute maskCustomAccessorOrValue(=CustomAccessor | CustomValue) instead ofCustomAccessor. Every neighbouring accessor row (validFrom,validTo,ca,fingerprint, ...) usesCustomAccessor. WhengetOwnPropertyDescriptorreifies the accessor it strips theCustomAccessorbit, but the strayCustomValuebit survives and trips the assertion insetAccessorDescriptor.Fix
Use
CustomAccessoron both rows, matching the rest of the table.Verification
test/js/node/crypto/x509.test.tsread the descriptors (single and whole-prototype walk) and call the extracted getters on an instance; they abort the debug build before the fix and pass after.test/js/node/crypto/x509.test.ts,x509-subclass.test.ts,test-crypto-x509.js, andtest-tls-getcertificate-x509.jsall pass with the fix.