Skip to content

Commit 60463cf

Browse files
authored
Merge pull request #12716 from ethereum/set-c-locale
Don't set locale used by C++ stdlib to the value from `LC_ALL` env variable even if it's valid
2 parents 401a046 + 2d834ea commit 60463cf

File tree

4 files changed

+99
-24
lines changed

4 files changed

+99
-24
lines changed

.circleci/config.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,20 @@ jobs:
10511051
t_ubu_release_cli: &t_ubu_release_cli
10521052
<<: *t_ubu_cli
10531053

1054+
t_ubu_locale:
1055+
<<: *base_ubuntu2004_small
1056+
steps:
1057+
- checkout
1058+
- attach_workspace:
1059+
at: build
1060+
- run:
1061+
name: Install all locales
1062+
command: |
1063+
apt update --assume-yes
1064+
apt install locales-all --assume-yes --no-install-recommends
1065+
- run: test/localeTest.sh build/solc/solc
1066+
- gitter_notify_failure_unless_pr
1067+
10541068
t_ubu_asan_cli:
10551069
# Runs slightly faster on medium but we only run it nightly so efficiency matters more.
10561070
<<: *base_ubuntu2004_small
@@ -1435,6 +1449,7 @@ workflows:
14351449
# Ubuntu build and tests
14361450
- b_ubu: *workflow_trigger_on_tags
14371451
- t_ubu_cli: *workflow_ubuntu2004
1452+
- t_ubu_locale: *workflow_ubuntu2004
14381453
- t_ubu_soltest_all: *workflow_ubuntu2004
14391454
- t_ubu_soltest_enforce_yul: *workflow_ubuntu2004
14401455
- b_ubu_clang: *workflow_trigger_on_tags

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Compiler Features:
1111

1212
Bugfixes:
1313
* Yul IR Code Generation: Optimize embedded creation code with correct settings. This fixes potential mismatches between the constructor code of a contract compiled in isolation and the bytecode in ``type(C).creationCode``, resp. the bytecode used for ``new C(...)``.
14+
* Fix internal error for locales with unusual capitalization rules. Locale set in the environment is now completely ignored.
1415

1516

1617
### 0.8.12 (2022-02-16)

solc/main.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,40 +27,16 @@
2727

2828
#include <boost/exception/all.hpp>
2929

30-
#include <clocale>
3130
#include <iostream>
3231

3332
using namespace std;
3433
using namespace solidity;
3534

36-
/*
37-
The equivalent of setlocale(LC_ALL, "C") is called before any user code is run.
38-
If the user has an invalid environment setting then it is possible for the call
39-
to set locale to fail, so there are only two possible actions, the first is to
40-
throw a runtime exception and cause the program to quit (default behaviour),
41-
or the second is to modify the environment to something sensible (least
42-
surprising behaviour).
43-
44-
The follow code produces the least surprising behaviour. It will use the user
45-
specified default locale if it is valid, and if not then it will modify the
46-
environment the process is running in to use a sensible default. This also means
47-
that users do not need to install language packs for their OS.
48-
*/
49-
static void setDefaultOrCLocale()
50-
{
51-
#if __unix__
52-
if (!std::setlocale(LC_ALL, ""))
53-
{
54-
setenv("LC_ALL", "C", 1);
55-
}
56-
#endif
57-
}
5835

5936
int main(int argc, char** argv)
6037
{
6138
try
6239
{
63-
setDefaultOrCLocale();
6440
solidity::frontend::CommandLineInterface cli(cin, cout, cerr);
6541
return cli.run(argc, argv) ? 0 : 1;
6642
}

test/localeTest.sh

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/usr/bin/env bash
2+
3+
#------------------------------------------------------------------------------
4+
# Script that tests that the compiler works correctly regardless of the locale
5+
# setting. As a prerequisite, the following locales must be enabled system-wide:
6+
# C, tr_TR.utf8, ja_JP.eucjp.
7+
#
8+
# Usage:
9+
# <script name>.sh <path to solc binary>
10+
#
11+
# ------------------------------------------------------------------------------
12+
# This file is part of solidity.
13+
#
14+
# solidity is free software: you can redistribute it and/or modify
15+
# it under the terms of the GNU General Public License as published by
16+
# the Free Software Foundation, either version 3 of the License, or
17+
# (at your option) any later version.
18+
#
19+
# solidity is distributed in the hope that it will be useful,
20+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+
# GNU General Public License for more details.
23+
#
24+
# You should have received a copy of the GNU General Public License
25+
# along with solidity. If not, see <http://www.gnu.org/licenses/>
26+
#
27+
# (c) 2022 solidity contributors.
28+
#------------------------------------------------------------------------------
29+
30+
set -eo pipefail
31+
32+
REPO_ROOT=$(cd "$(dirname "$0")/.." && pwd)
33+
# shellcheck source=scripts/common.sh
34+
source "${REPO_ROOT}/scripts/common.sh"
35+
36+
solc_binary="$1"
37+
(( $# == 1 )) || fail "Expected exactly 1 argument."
38+
39+
# This test won't work without some specific locales installed
40+
locale -a | grep -e "^tr_TR\.utf8$" || fail "Locale 'tr_TR.utf8' not available."
41+
locale -a | grep -e "^ja_JP\.eucjp$" || fail "Locale 'ja_JP.eucjp' not available."
42+
locale -a | grep -e "^C$" || fail "Locale 'C' not available."
43+
locale -a | grep -e "^__invalid_locale__$" && fail "'__invalid_locale__' is not supposed to be a valid locale name."
44+
45+
i="i"
46+
47+
test_code=$(cat <<'EOF'
48+
// SPDX-License-Identifier: GPL-3.0
49+
pragma solidity *;
50+
library L {}
51+
EOF
52+
)
53+
54+
# Whatever locale is set by default.
55+
printTask "Testing the default locale..."
56+
default_locale_output=$(echo "$test_code" | "$solc_binary" - --bin)
57+
58+
# Plain C locale
59+
printTask "Testing the C locale..."
60+
export LC_ALL=C
61+
[[ ${i^^} == "I" ]] || assertFail
62+
c_locale_output=$(echo "$test_code" | "$solc_binary" - --bin)
63+
diff_values "$default_locale_output" "$c_locale_output"
64+
65+
# Turkish locale, which has capitalization rules (`i` -> `İ` and `I` to `ı`) that can make identifiers invalid.
66+
printTask "Testing the Turkish locale..."
67+
export LC_ALL=tr_TR.utf8
68+
[[ ${i^^} != "I" ]] || assertFail
69+
tr_locale_output=$(echo "$test_code" | "$solc_binary" - --bin)
70+
diff_values "$default_locale_output" "$tr_locale_output"
71+
72+
# A different locale, that should not do anything special to ASCII chars.
73+
printTask "Testing the Japanese locale..."
74+
export LC_ALL=ja_JP.eucjp
75+
[[ ${i^^} == "I" ]] || assertFail
76+
ja_locale_output=$(echo "$test_code" | "$solc_binary" - --bin)
77+
diff_values "$default_locale_output" "$ja_locale_output"
78+
79+
# The compiler should not crash if the locale is not valid.
80+
printTask "Testing an invalid locale..."
81+
export LC_ALL=__invalid_locale__ || true
82+
invalid_locale_output=$(echo "$test_code" | "$solc_binary" - --bin)
83+
diff_values "$default_locale_output" "$invalid_locale_output"

0 commit comments

Comments
 (0)