Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
1212-lists_to_integer-friends-Don-t-crash-for-o...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1212-lists_to_integer-friends-Don-t-crash-for-overlong-li.patch of Package erlang
From 47ef6142984c312ee6b39257dc40f5dab00534eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Sun, 29 May 2022 10:34:39 +0200 Subject: [PATCH] lists_to_integer() & friends: Don't crash for overlong lists Let `list_to_integer/1` and `list_to_integer/2` raise a `system_limit` exception when the result doesn't fit in a bignum. Let `string:to_integer/1` return `{error,system_limit}` when the result doesn't fit. --- erts/emulator/beam/bif.c | 38 ++++++++++++++++----------- erts/emulator/beam/big.c | 5 ++++ erts/emulator/beam/big.h | 3 ++- erts/emulator/test/list_bif_SUITE.erl | 11 ++++++-- erts/emulator/test/num_bif_SUITE.erl | 8 +++--- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index fa359c5e28..c4687f04b8 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -3357,6 +3357,9 @@ BIF_RETTYPE string_list_to_integer_1(BIF_ALIST_1) case LTI_NO_INTEGER: hp = HAlloc(BIF_P,3); BIF_RET(TUPLE2(hp, am_error, am_no_integer)); + case LTI_SYSTEM_LIMIT: + hp = HAlloc(BIF_P,3); + BIF_RET(TUPLE2(hp, am_error, am_system_limit)); default: hp = HAlloc(BIF_P,3); BIF_RET(TUPLE2(hp, res, tail)); @@ -3365,25 +3368,27 @@ BIF_RETTYPE string_list_to_integer_1(BIF_ALIST_1) BIF_RETTYPE list_to_integer_1(BIF_ALIST_1) { - /* Using erts_list_to_integer is about twice as fast as using - erts_chars_to_integer because we do not have to copy the - entire list */ + /* Using erts_list_to_integer() is about twice as fast as using + * erts_chars_to_integer() because we do not have to copy the + * entire list. */ Eterm res; Eterm dummy; /* must be a list */ - if (erts_list_to_integer(BIF_P, BIF_ARG_1, 10, - &res, &dummy) != LTI_ALL_INTEGER) { - BIF_ERROR(BIF_P,BADARG); + switch (erts_list_to_integer(BIF_P, BIF_ARG_1, 10, &res, &dummy)) { + case LTI_ALL_INTEGER: + BIF_RET(res); + case LTI_SYSTEM_LIMIT: + BIF_ERROR(BIF_P, SYSTEM_LIMIT); + default: + BIF_ERROR(BIF_P, BADARG); } - BIF_RET(res); } BIF_RETTYPE list_to_integer_2(BIF_ALIST_2) { - /* Bif implementation is about 50% faster than pure erlang, - and since we have erts_chars_to_integer now it is simpler - as well. This could be optimized further if we did not have to - copy the list to buf. */ + /* The BIF implementation is about 50% faster than pure Erlang, + * and since we now have erts_list_to_integer() it is simpler as + * well. */ Sint i; Eterm res, dummy; int base; @@ -3399,11 +3404,14 @@ BIF_RETTYPE list_to_integer_2(BIF_ALIST_2) BIF_ERROR(BIF_P, BADARG); } - if (erts_list_to_integer(BIF_P, BIF_ARG_1, base, - &res, &dummy) != LTI_ALL_INTEGER) { - BIF_ERROR(BIF_P,BADARG); + switch (erts_list_to_integer(BIF_P, BIF_ARG_1, base, &res, &dummy)) { + case LTI_ALL_INTEGER: + BIF_RET(res); + case LTI_SYSTEM_LIMIT: + BIF_ERROR(BIF_P, SYSTEM_LIMIT); + default: + BIF_ERROR(BIF_P, BADARG); } - BIF_RET(res); } /**********************************************************************/ diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index 5a8f6216c7..8439a8c08f 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -3008,6 +3008,11 @@ LTI_result_t erts_list_to_integer(Process *BIF_P, Eterm orig_list, m = (lg2+D_EXP-1)/D_EXP; /* number of digits */ m = BIG_NEED_SIZE(m); /* number of words + thing */ + if (m > BIG_ARITY_MAX) { + error_res = LTI_SYSTEM_LIMIT; + goto error; + } + hp = HAlloc(BIF_P, m); hp_end = hp + m; diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h index 8fe9fb1cc4..73505569b3 100644 --- a/erts/emulator/beam/big.h +++ b/erts/emulator/beam/big.h @@ -188,7 +188,8 @@ typedef enum { LTI_BAD_STRUCTURE = 0, LTI_NO_INTEGER = 1, LTI_SOME_INTEGER = 2, - LTI_ALL_INTEGER = 3 + LTI_ALL_INTEGER = 3, + LTI_SYSTEM_LIMIT = 4, } LTI_result_t; LTI_result_t erts_list_to_integer(Process *BIF_P, Eterm orig_list, diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl index b6941bfa43..2e43e9ad5a 100644 --- a/erts/emulator/test/list_bif_SUITE.erl +++ b/erts/emulator/test/list_bif_SUITE.erl @@ -50,14 +50,21 @@ t_list_to_integer(Config) when is_list(Config) -> 12373 = (catch list_to_integer("12373")), -12373 = (catch list_to_integer("-12373")), 12373 = (catch list_to_integer("+12373")), - {'EXIT',{badarg,_}} = ( catch list_to_integer(abc)), + {'EXIT',{badarg,_}} = (catch list_to_integer(abc)), {'EXIT',{badarg,_}} = (catch list_to_integer("")), {12373281903728109372810937209817320981321,"ABC"} = string:to_integer("12373281903728109372810937209817320981321ABC"), {-12373281903728109372810937209817320981321,"ABC"} = string:to_integer("-12373281903728109372810937209817320981321ABC"), {12,[345]} = string:to_integer([$1,$2,345]), - {error, badarg} = string:to_integer([$1,$2,a]), + {error,badarg} = string:to_integer([$1,$2,a]), {error,no_integer} = string:to_integer([$A]), {error,badarg} = string:to_integer($A), + + %% System limit. + Digits = lists:duplicate(11_000_000, $9), + {'EXIT',{system_limit,_}} = catch list_to_integer(Digits), + {'EXIT',{system_limit,_}} = catch list_to_integer(Digits, 16), + {error,system_limit} = string:to_integer(Digits), + ok. %% Test hd/1 with correct and incorrect arguments. diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl index 78a232de8a..3b9aa4df30 100644 --- a/erts/emulator/test/num_bif_SUITE.erl +++ b/erts/emulator/test/num_bif_SUITE.erl @@ -670,9 +670,11 @@ t_string_to_integer(Config) when is_list(Config) -> {"10",''} %Base 20 ]), - %% log2 calculation overflow bug in do_integer_to_list (OTP-12624). - %% Would crash with segmentation fault. - 0 = list_to_integer(lists:duplicate(10000000,$0)), + %% System limit + Digits = lists:duplicate(11_000_000, $9), + {'EXIT',{system_limit,_}} = catch list_to_integer(Digits), + {'EXIT',{system_limit,_}} = catch list_to_integer(Digits, 16), + {error,system_limit} = string:to_integer(Digits), ok. -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor