Skip to content

Reject a reentrant Psych::Parser#parse on JRuby - #821

Open
youdie006 wants to merge 1 commit into
ruby:masterfrom
youdie006:jruby-parser-reentrancy
Open

Reject a reentrant Psych::Parser#parse on JRuby#821
youdie006 wants to merge 1 commit into
ruby:masterfrom
youdie006:jruby-parser-reentrancy

Conversation

@youdie006

@youdie006 youdie006 commented Sep 11, 2026

Copy link
Copy Markdown

#817 fixed Psych::Parser#parse reentrancy in ext/psych/psych_parser.c and ext/psych/psych_parser_fy.c. ext/java/org/jruby/ext/psych/PsychParser.java is the third implementation of the same method and did not get the guard, which is why that PR marked both of its new tests pend "Failing on JRuby".

parser is an instance field (PsychParser.java:568), assigned at :241 and driven by the loop at :248. A handler calling parse again replaces the ParserImpl the outer loop is still draining:

parser.parse "--- [a, b, c]\n"   # handler#scalar calls parser.parse("--- inner\n")

delivers ["a", "inner"] with no error, where the C backends deliver ["a", "b", "c"] and raise Psych::Exception out of the inner call.

The change mirrors the C fix — same flag, same exception class, same message string, finally standing in for rb_ensure. No new test: #817 already wrote them, so this only deletes the two pend lines. The other four pend "Failing on JRuby" lines in that file are a separate Psych::Parser#mark gap and are untouched.

Verification

Built in jruby:9.4-jdk21 against a compile of this repo's Java sources. Every row asserts which PsychParser was loaded, because with the classpath unset this silently tests JRuby's bundled psych.jar.

row result
current master 2 tests, 1 failure, 1 error (test_parser.rb:128)
with the fix 2 tests, 7 assertions, 0 failures, 0 errors
revert identical to master
keep the flag, drop finally { parsing = false; } 0 failures but 1 error at test_parser.rb:135

That last row is the useful one: without the finally the reentrancy check still passes, and only the "reusable afterwards" assertion — the one #817's own comment describes — catches the poisoned flag.

result
JRuby 9.4.15.0, all of test/psych 657 tests, 1576 assertions, 0 failures, 14 pendings
CRuby 3.2.11, test/psych/test_parser.rb 49 tests, 92 assertions, 0 failures

The removed pends are RUBY_PLATFORM =~ /java/-guarded, so they were already no-ops on CRuby and the C sources are untouched; the same reasoning covers the truffleruby rows and libfyaml.yml, which I did not execute. I compiled against snakeyaml-engine 2.9 while the repo pins 2.10; the patch touches no snakeyaml API.


Disclosure: I used Claude (an AI assistant) while preparing this change. Every result above I ran and verified myself.

ruby#817 added this guard to both C backends but not to the Java one, where
the parser is an instance field: a handler calling parse again replaces
the ParserImpl the outer loop is still draining, so the outer document
is truncated and the inner document's events are spliced into it.

Re-enables the two reentrancy tests that ruby#817 marked pending on JRuby.
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.

1 participant