Skip to content

(Hopefully) Fix use after free#54

Merged
hsbt merged 1 commit into
ruby:masterfrom
RDIL:reece/use-after-free
Jun 24, 2026
Merged

(Hopefully) Fix use after free#54
hsbt merged 1 commit into
ruby:masterfrom
RDIL:reece/use-after-free

Conversation

@RDIL

@RDIL RDIL commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Disclaimer: this patch was written with the assistance of a large language model (Claude Opus 4.7 with 1M context). I am very unfamiliar with C, so it's completely possible that it has made any number of mistakes.

Between v1.4.1 and v1.5.1.1, #40 added a GC mark function to the SyckNode Data wrapper created inside rb_syck_load_handler. The change fixed one crash (GC collecting node children mid-parse) but opened a new one: the parser frees the node the moment the handler returns, so any later GC that still reaches the wrapper, via a conservative stack root, calls the mark function on a dangling pointer.

Possibly fixes #50 (it gets rid of it in my testing, but it's possible this has other implications I haven't thought of, or is only a partial fix)

cc @peterzhu2118

Resources used while making this PR: https://gist.github.com/RDIL/5e2bda4041ed3b804449472a9bf7d809

Note: build is blocked on #56

@RDIL RDIL mentioned this pull request Apr 18, 2026
RDIL added a commit to RDIL/syck that referenced this pull request Apr 18, 2026
While working on ruby#54, I found that ASAN flags this line because this function call tries to read 53 bytes of a 50-byte string. That's not right!
@RDIL RDIL mentioned this pull request Apr 18, 2026
@kevingswift

Copy link
Copy Markdown

Strangely I had the same fix from Claude only a few days ago. The test program i wrote ran ok, but not had time to check this out in the main product yet. In my testing I found the check for n being null "if ( n == NULL ) return;" didn't seem to be required but there is no harm in it.

hsbt pushed a commit to RDIL/syck that referenced this pull request Jun 24, 2026
While working on ruby#54, I found that ASAN flags this line because this function call tries to read 53 bytes of a 50-byte string. That's not right!
@hsbt hsbt force-pushed the reece/use-after-free branch from cf30f72 to 4dacaa3 Compare June 24, 2026 07:52
Between v1.4.1 and v1.5.1.1, 6793d14 added a GC mark function to the `SyckNode` Data wrapper created inside `rb_syck_load_handler`. The change fixed one crash (GC collecting node children mid-parse) but opened a new one: the parser frees the node the moment the handler returns, so any later GC that still reaches the wrapper, via a conservative stack root, calls the mark function on a dangling pointer.
@hsbt hsbt force-pushed the reece/use-after-free branch from 4dacaa3 to 29aba52 Compare June 24, 2026 07:53
@hsbt hsbt marked this pull request as ready for review June 24, 2026 07:53
@hsbt

hsbt commented Jun 24, 2026

Copy link
Copy Markdown
Member

@RDIL I rebased with the recent fixes with build failure and push your branch. Your fix seems correct. But I couldn't reproduce my ASAN build and investigation.

I will merge and ship new version. I hope this fix #50

@hsbt hsbt merged commit 6a5b897 into ruby:master Jun 24, 2026
25 of 48 checks passed
@RDIL RDIL deleted the reece/use-after-free branch June 24, 2026 18:13
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.

Segfaults on v1.5+

3 participants