Skip to content

Commit 30ae485

Browse files
authored
[libcxx] Work around picolibc argv handling in tests. (#127662)
This fixes some test failures when the libcxx tests are run against an up-to-date picolibc on embedded Arm, because those tests depend on an unsupported locale but the `hasAnyLocale` preliminary check wrongly concluded that the locale _was_ supported. `hasAnyLocale` passes a set of locale strings to a test program via the command line, and checks if the libc under test reports that any of the locales can be successfully set via setlocale(). In some invocations one of the locale names contains a space, e.g. the Windows-style locale name "English_United States.1252". Unfortunately picolibc's crt0, when running under Arm semihosting, fetches the single command string from the host and then splits it up at spaces without implementing any kind of quoting. So it simply isn't possible to get a space into an argv word. As a result, we end up testing for the locale (in this example) "English_United". In up-to-date versions of picolibc, this is actually accepted, since it contains no objectionable character set specification (or indeed any at all). So the lit check wrongly concludes that libc supports that locale, and enables some locale tests, which fail. This patch works around the issue entirely within `hasAnyLocale()`, by abandoning the use of argv completely, and instead encoding the list of locales to check as an array of strings inside the test program.
1 parent ad3f7d2 commit 30ae485

File tree

1 file changed

+24
-7
lines changed
  • libcxx/utils/libcxx/test

1 file changed

+24
-7
lines changed

libcxx/utils/libcxx/test/dsl.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import os
1010
import pickle
1111
import platform
12-
import shlex
1312
import shutil
1413
import tempfile
1514

@@ -274,23 +273,41 @@ def hasAnyLocale(config, locales):
274273
%{exec} -- this means that the command may be executed on a remote host
275274
depending on the %{exec} substitution.
276275
"""
277-
program = """
276+
277+
# Convert the locale names into C string literals. We expect all currently
278+
# known locale names to be printable ASCII and not contain awkward
279+
# characters like \ or ", so this should be trivial.
280+
assert all(
281+
0x20 <= ord(ch) <= 0x7E and ch not in {'"', "\\"}
282+
for locale in locales
283+
for ch in locale
284+
)
285+
name_string_literals = ", ".join('"' + locale + '"' for locale in locales)
286+
287+
program = (
288+
"""
278289
#include <stddef.h>
279290
#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_LOCALIZATION
280291
int main(int, char**) { return 1; }
281292
#else
282293
#include <locale.h>
283-
int main(int argc, char** argv) {
284-
for (int i = 1; i < argc; i++) {
285-
if (::setlocale(LC_ALL, argv[i]) != NULL) {
294+
static const char *const test_locale_names[] = {
295+
"""
296+
+ name_string_literals
297+
+ """, nullptr,
298+
};
299+
int main() {
300+
for (size_t i = 0; test_locale_names[i]; i++) {
301+
if (::setlocale(LC_ALL, test_locale_names[i]) != NULL) {
286302
return 0;
287303
}
288304
}
289305
return 1;
290306
}
291307
#endif
292-
"""
293-
return programSucceeds(config, program, args=[shlex.quote(l) for l in locales])
308+
"""
309+
)
310+
return programSucceeds(config, program)
294311

295312

296313
@_memoizeExpensiveOperation(lambda c, flags="": (c.substitutions, c.environment, flags))

0 commit comments

Comments
 (0)