Opened 9 years ago
Closed 9 years ago
#1272 closed defect (fixed)
string->number crash
Reported by: | Mario Domenech Goulart | Owned by: | |
---|---|---|---|
Priority: | critical | Milestone: | 4.11.0 |
Component: | core libraries | Version: | 4.10.x |
Keywords: | string->number | Cc: | |
Estimated difficulty: |
Description
Reported by tilpner on IRC:
$ csi CHICKEN (c) 2008-2015, The CHICKEN Team (c) 2000-2007, Felix L. Winkelmann Version 4.10.0 (rev b259631) linux-unix-gnu-x86-64 [ 64bit manyargs dload ptables ] compiled 2015-08-04 on yves.more-magic.net (Linux) #;1> (string->number "42" 60) Error: segmentation violation Call history: <syntax> (string->number "42" 60) <eval> (string->number "42" 60) <--
Change History (4)
comment:1 Changed 9 years ago by
comment:2 Changed 9 years ago by
OK, my analysis of yesterday was a bit too hasty: C_LONG_MAX
is also conditionally declared to be either LONG_MAX
or LONG_LONG_MAX
. This is all correct.
The handling of error situations seems to be the problem: the C_LONG_MAX
/C_LONG_MIN
values are returned iff the result is an overflow or underflow. However, the (draft) spec also says "If no conversion could be performed, zero is returned", and this is what is happening here. eptr
is never even touched (though the spec doesn't say if this may happen).
comment:3 Changed 9 years ago by
Because the spec says nothing about what happens if the base is outside the supported 2..36 range, we should avoid passing in such values in the first place.
comment:4 Changed 9 years ago by
Resolution: | → fixed |
---|---|
Status: | new → closed |
Fixed by 76a84c3 and 2d5ff60.
Oh my, this is nasty!
We first call
C_strow()
to attempt a conversion (and if it fails we roll our own). This is eitherstrol()
orstroll()
depending on platform.And what does the glibc manual state?
So this breaks the spec (because
ERANGE
isn't supported by C99), and we only check for errnoEINVAL
. If errno has any other value, we dereferenceeptr
, the end pointer which will have an unspecified value if it returned an error!I'm not sure what the correct fix would be here. I suppose we should just ignore
errno
, or bail out if we see an unexpected one with(n == C_LONG_MAX || n == C_LONG_MIN)
. But what if the return value just happens to actually be that value?Also, if we're using
stroll
, we should actually be checking forC_LLONG_MAX
orC_LLONG_MIN
instead ofC_LONG_MAX
/C_LONG_MIN
.In CHICKEN 5, this problem should be gone because this function has been completely replaced by a full numeric tower-aware version.