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

Fix uniqint SIGSEGV for objects with no int overload #138

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

zhmylove
Copy link

@zhmylove zhmylove commented Jan 26, 2025

In case uniqint takes several objects, it always tries to call their int overload using amagic_call. This patch fixes the case when amagic_call returned NULL resulting into Segmentation Violation. Several tests are also added to ensure proper objects handling.

Problem:
The code below expected to work but crashes with SIGSEGV.

use List::Util qw( uniqint );
{ package Foo; use overload "+" => sub {1} }
uniqint bless {}, "Foo"; # Foo has no 'int' overload unlike Math::BigInt
| SvAMAGIC | AMG_CALLun | Current result | Proposed result |
+----------+------------+----------------+-----------------+
| false    | false      | else branch    | else branch     |
| false    | true       | else branch    | else branch     |
| true     | false      | SIGSEGV        | croak like int()|
| true     | true       | else bypassed  | else bypassed   |

In case uniqint takes several objects, it always tries to call their
int overload using amagic_call.  This patch fixes the case when
amagic_call returned NULL resulting into Segmentation Violation.
Several tests are also added to ensure proper objects handling.

Signed-off-by: Sergei Zhmylev <[email protected]>
@zhmylove zhmylove force-pushed the dev/korg/sigsegv-uniqint-croak branch from 76bb5f9 to 39e539e Compare January 26, 2025 22:35
if(SvAMAGIC(arg) && (arg = AMG_CALLun(arg, int)))
; /* nothing to do */
if(SvAMAGIC(arg)) {
if(!(arg = AMG_CALLun(arg, int)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. This adds a new exception condition where there didn't used to be one. I wonder if that change in behaviour would break too much.

I'd prefer to preserve the existing condition, but without trashing the arg value. Instead, perhaps have:

SV *mgret;
if(SvAMAGIC(arg) && (mgret = AMG_CALLun(arg, int)))
    arg = mgret;
else ...

that way, it keeps the existing condition, but does not trash the value in arg when there is some magic but no int_amg.

Copy link
Author

@zhmylove zhmylove Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
Yes, I actually suggested this particular change in #137

But after that I thought a little bit more about that and decided to write this with croak just like int() does in this situation. Mostly due to uniqint() means literally: "remove subsequent duplicates based on int() values of the list supplied to it" and in turn int() does croak() for such objects.

This change will definitely not break any existing code as it croaks only instead of Segmentation Violation error which causes exit even inside eval

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A croak seems appropriate to me, since that is what a missing overload does anywhere else.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahyes. In that case, does the message match what would happen normally?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message does not match.

But looking at the code for amagic_call, it isn't obvious why the previous code isn't already working correctly. It seems like it should already be producing an appropriate croak if the overload doesn't exist.

@leonerd
Copy link
Contributor

leonerd commented Feb 4, 2025

The Perl 5.6 smoker looks unhappy, but looks like a machine setup issue, unrelated to this change.

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