Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer libxml2's strdup and strchr equivalents #1517

Merged
merged 1 commit into from
May 10, 2017

Conversation

jeremy
Copy link
Contributor

@jeremy jeremy commented Jul 27, 2016

Background: Working around a puzzling segfault when using libc strdup on a C string from Ruby. Returns a pointer that's outside the program heap entirely.

Turns out libxml2 provides its own strdup/strchr equivalents that use the mem management functions we pass it (including ruby's malloc, ruby_strdup, etc), so may as well prefer these anyway.

@tenderlove
Copy link
Member

Background: it seems like some platforms may not actually behave nicely if you use strdup from libc. So we should probably try to avoid using strdup.

@flavorjones
Copy link
Member

Thanks for submitting this!

Do you have a way to reliably reproduce the segfault? I'd like to verify
the expected behavior and potentially add something to the test suite to
prevent regression.

On Jul 27, 2016 6:35 PM, "Aaron Patterson" [email protected] wrote:

Background: it seems like some platforms may not actually behave nicely
if you use strdup from libc
https://stackoverflow.com/questions/8359966/strdup-returning-address-out-of-bounds.
So we should probably try to avoid using strdup.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#1517 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAgD2jkHXBx0qxJch_WLoovM2oDLk28ks5qZ90qgaJpZM4JWscV
.

@flavorjones
Copy link
Member

Hmm, ok, now that I'm looking at the diff maybe that's not necessary.

@jeremy
Copy link
Contributor Author

jeremy commented Jul 28, 2016

@flavorjones Confirm; the segfault is unrelated. I'm seeing libc strdup intermittently return total nonsense in… some cases and that happens to trigger a segfault in strchr since it gets a pointer to memory it can't access.

Using the xmlStrdupFunc we provided to xmlMemSetup (Ruby's ruby_strdup) happens to work around this issue as a side effect.

@flavorjones
Copy link
Member

@jeremy I'm not sure if you still think this should be merged? Your most recent comment above seems to indicate that the problem you're trying to solve may be unrelated?

@jeremy
Copy link
Contributor Author

jeremy commented Jan 22, 2017

Yes, it should. I've been running this in production for months now and it completely solves the issue I hit.

Here's the problem I was troubleshooting: "using libc strdup on a C string from Ruby was returning a pointer that's outside the program heap entirely." This then caused strchr to segfault.

This patch obviates the root issue with strdup by using libxml's mem management API which internally delegates to Ruby mem handling routines. That fixes the strdup issue I hit in certain environments, which means we never hit the strchr segfault.

This is good hygiene as a user of libxml in any case, too!

(That said, being able to segfault at all here is troubling. We aren't doing any error checking.)

(Working around a puzzling segfault when using libc strdup on a C string
from Ruby.)
@flavorjones
Copy link
Member

@jeremy Thanks so much for submitting this and for persisting. Merging!

@flavorjones flavorjones merged commit 1691c0d into sparklemotion:master May 10, 2017
@flavorjones flavorjones added this to the 1.8.0 milestone May 10, 2017
@jeremy jeremy deleted the xmlstrdup branch May 10, 2017 05:53
richardcockerill pushed a commit to myfoodlink/creek that referenced this pull request Jul 7, 2017
jeremy added a commit to jeremy/bcrypt-ruby that referenced this pull request Nov 27, 2019
Caused by compiler confusion about what to export from string.h,
depending on ANSI/ISO C standards used. When strdup isn't exported,
GCC provides a builtin. When cross-compiled for another platform,
this can lead to returning a 32-bit pointer instead of 64-bit ->
segfault.

Fix by including ruby/util.h which unsets and redefines strdup as
ruby_strdup, a portable implementation.

Further reading
* https://stackoverflow.com/questions/8359966/strdup-returning-address-out-of-bounds
* https://bitbucket.org/einsteintoolkit/tickets/issues/1816

Similar issue affected Nokogiri, with a similar fix:
* sparklemotion/nokogiri#1517
jeremy added a commit to jeremy/bcrypt-ruby that referenced this pull request Nov 27, 2019
Caused by compiler confusion about what to export from string.h,
depending on ANSI/ISO C standards used. When strdup isn't exported,
GCC provides a builtin. When cross-compiled for another platform,
this can lead to returning a 32-bit pointer instead of 64-bit ->
segfault.

Fix by including ruby/util.h which unsets and redefines strdup as
ruby_strdup, a portable implementation.

Further reading
* https://stackoverflow.com/questions/8359966/strdup-returning-address-out-of-bounds
* https://bitbucket.org/einsteintoolkit/tickets/issues/1816

Similar issue affected Nokogiri, with a similar fix:
* sparklemotion/nokogiri#1517
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.

3 participants