From a00f10d6e65f64d3b47e7c32e82c6ccf611d46ff Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 26 Jun 2018 15:05:00 +0200 Subject: stdlib: Improve error handling in module io_lib --- lib/stdlib/src/io_lib.erl | 49 ++++++++++++++++++++++++++++++++------------ lib/stdlib/test/io_SUITE.erl | 12 +++++++++-- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl index 3a5aba60b4..8223a52873 100644 --- a/lib/stdlib/src/io_lib.erl +++ b/lib/stdlib/src/io_lib.erl @@ -178,11 +178,11 @@ fread(Cont, Chars, Format) -> Data :: [term()]. format(Format, Args) -> - case catch io_lib_format:fwrite(Format, Args) of - {'EXIT',_} -> - erlang:error(badarg, [Format, Args]); - Other -> - Other + try io_lib_format:fwrite(Format, Args) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) end. -spec format(Format, Data, Options) -> chars() when @@ -193,11 +193,11 @@ format(Format, Args) -> CharsLimit :: chars_limit(). format(Format, Args, Options) -> - case catch io_lib_format:fwrite(Format, Args, Options) of - {'EXIT',_} -> - erlang:error(badarg, [Format, Args, Options]); - Other -> - Other + try io_lib_format:fwrite(Format, Args, Options) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) end. -spec scan_format(Format, Data) -> FormatList when @@ -208,7 +208,9 @@ format(Format, Args, Options) -> scan_format(Format, Args) -> try io_lib_format:scan(Format, Args) catch - _:_ -> erlang:error(badarg, [Format, Args]) + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) end. -spec unscan_format(FormatList) -> {Format, Data} when @@ -223,7 +225,12 @@ unscan_format(FormatList) -> FormatList :: [char() | format_spec()]. build_text(FormatList) -> - io_lib_format:build(FormatList). + try io_lib_format:build(FormatList) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [FormatList]) + end. -spec build_text(FormatList, Options) -> chars() when FormatList :: [char() | format_spec()], @@ -232,7 +239,23 @@ build_text(FormatList) -> CharsLimit :: chars_limit(). build_text(FormatList, Options) -> - io_lib_format:build(FormatList, Options). + try io_lib_format:build(FormatList, Options) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [FormatList, Options]) + end. + +%% Failure to load a module must not be labeled as badarg. +%% C, R, and S are included so that the original error, which could be +%% a bug in io_lib_format, can be found by tracing on +%% test_modules_loaded/3. +test_modules_loaded(_C, _R, _S) -> + Modules = [io_lib_format, io_lib_pretty, string, unicode], + case code:ensure_modules_loaded(Modules) of + ok -> ok; + Error -> erlang:error(Error) + end. -spec print(Term) -> chars() when Term :: term(). diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 79cee54335..f097552e8c 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -31,7 +31,7 @@ otp_10836/1, io_lib_width_too_small/1, io_with_huge_message_queue/1, format_string/1, maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1, - otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, + otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1, otp_15159/1]). -export([pretty/2, trf/3]). @@ -64,7 +64,7 @@ all() -> io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836, io_lib_width_too_small, io_with_huge_message_queue, format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175, - otp_14285, limit_term, otp_14983, otp_15103, otp_15159]. + otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159]. %% Error cases for output. error_1(Config) when is_list(Config) -> @@ -2639,3 +2639,11 @@ otp_15159(_Config) -> "[atom]" = lists:flatten(io_lib:format("~p", [[atom]], [{chars_limit,5}])), ok. + +otp_15076(_Config) -> + {'EXIT', {badarg, _}} = (catch io_lib:format("~c", [a])), + L = io_lib:scan_format("~c", [a]), + {"~c", [a]} = io_lib:unscan_format(L), + {'EXIT', {badarg, _}} = (catch io_lib:build_text(L)), + {'EXIT', {badarg, _}} = (catch io_lib:build_text(L, [])), + ok. -- cgit v1.2.3