Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 5f99b02

Browse files
committed
towctrans() should return the input and set errno on failure.
POSIX says that towctrans() and towctrans_l() "return wc unchanged" on failure. We were returning 0 instead. Technically, POSIX says that errno _may_ be set if the wctrans_t argument is invalid, which is presumably why musl/glibc do nothing. But FreeBSD (and thus iOS) set errno to EINVAL, and bionic was already setting errno to EINVAL for wctrans(), so let's be consistent with ourselves and the OS that folks are most likely to be porting code to/from. (Noticed by inspection.) Change-Id: I63e252d588ddfb7c6ead58d04c690d7b85f23374
1 parent f4ef9a5 commit 5f99b02

File tree

2 files changed

+46
-15
lines changed

2 files changed

+46
-15
lines changed

libc/bionic/wctype.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ static wctrans_t wctrans_toupper = wctrans_t(2);
158158
wctrans_t wctrans(const char* name) {
159159
if (strcmp(name, "tolower") == 0) return wctrans_tolower;
160160
if (strcmp(name, "toupper") == 0) return wctrans_toupper;
161+
errno = EINVAL;
161162
return nullptr;
162163
}
163164

@@ -169,7 +170,7 @@ wint_t towctrans(wint_t c, wctrans_t t) {
169170
if (t == wctrans_tolower) return towlower(c);
170171
if (t == wctrans_toupper) return towupper(c);
171172
errno = EINVAL;
172-
return 0;
173+
return c;
173174
}
174175

175176
wint_t towctrans_l(wint_t c, wctrans_t t, locale_t) {

tests/wctype_test.cpp

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -218,34 +218,64 @@ TEST(wctype, iswctype_l) {
218218
EXPECT_EQ(0, iswctype_l(WEOF, wctype_l("alnum", l.l), l.l));
219219
}
220220

221-
TEST(wctype, towctrans) {
221+
TEST(wctype, wctrans) {
222222
EXPECT_TRUE(wctrans("tolower") != nullptr);
223223
EXPECT_TRUE(wctrans("toupper") != nullptr);
224224

225+
errno = 0;
225226
EXPECT_TRUE(wctrans("monkeys") == nullptr);
227+
#if defined(__BIONIC__)
228+
// Android/FreeBSD/iOS set errno, but musl/glibc don't.
229+
EXPECT_ERRNO(EINVAL);
230+
#endif
226231
}
227232

228-
TEST(wctype, towctrans_l) {
233+
TEST(wctype, wctrans_l) {
229234
UtfLocale l;
230235
EXPECT_TRUE(wctrans_l("tolower", l.l) != nullptr);
231236
EXPECT_TRUE(wctrans_l("toupper", l.l) != nullptr);
232237

238+
errno = 0;
233239
EXPECT_TRUE(wctrans_l("monkeys", l.l) == nullptr);
240+
#if defined(__BIONIC__)
241+
// Android/FreeBSD/iOS set errno, but musl/glibc don't.
242+
EXPECT_ERRNO(EINVAL);
243+
#endif
234244
}
235245

236-
TEST(wctype, wctrans) {
237-
EXPECT_EQ(wint_t('a'), towctrans(L'A', wctrans("tolower")));
238-
EXPECT_EQ(WEOF, towctrans(WEOF, wctrans("tolower")));
239-
240-
EXPECT_EQ(wint_t('A'), towctrans(L'a', wctrans("toupper")));
241-
EXPECT_EQ(WEOF, towctrans(WEOF, wctrans("toupper")));
246+
TEST(wctype, towctrans) {
247+
wctrans_t lower = wctrans("tolower");
248+
EXPECT_EQ(wint_t('a'), towctrans(L'A', lower));
249+
EXPECT_EQ(WEOF, towctrans(WEOF, lower));
250+
251+
wctrans_t upper = wctrans("toupper");
252+
EXPECT_EQ(wint_t('A'), towctrans(L'a', upper));
253+
EXPECT_EQ(WEOF, towctrans(WEOF, upper));
254+
255+
wctrans_t invalid = wctrans("monkeys");
256+
errno = 0;
257+
EXPECT_EQ(wint_t('a'), towctrans(L'a', invalid));
258+
#if defined(__BIONIC__)
259+
// Android/FreeBSD/iOS set errno, but musl/glibc don't.
260+
EXPECT_ERRNO(EINVAL);
261+
#endif
242262
}
243263

244-
TEST(wctype, wctrans_l) {
264+
TEST(wctype, towctrans_l) {
245265
UtfLocale l;
246-
EXPECT_EQ(wint_t('a'), towctrans_l(L'A', wctrans_l("tolower", l.l), l.l));
247-
EXPECT_EQ(WEOF, towctrans_l(WEOF, wctrans_l("tolower", l.l), l.l));
248-
249-
EXPECT_EQ(wint_t('A'), towctrans_l(L'a', wctrans_l("toupper", l.l), l.l));
250-
EXPECT_EQ(WEOF, towctrans_l(WEOF, wctrans_l("toupper", l.l), l.l));
266+
wctrans_t lower = wctrans_l("tolower", l.l);
267+
EXPECT_EQ(wint_t('a'), towctrans_l(L'A', lower, l.l));
268+
EXPECT_EQ(WEOF, towctrans_l(WEOF, lower, l.l));
269+
270+
wctrans_t upper = wctrans_l("toupper", l.l);
271+
EXPECT_EQ(wint_t('A'), towctrans_l(L'a', upper, l.l));
272+
EXPECT_EQ(WEOF, towctrans_l(WEOF, upper, l.l));
273+
274+
wctrans_t invalid = wctrans_l("monkeys", l.l);
275+
errno = 0;
276+
EXPECT_EQ(wint_t('a'), towctrans_l(L'a', invalid, l.l));
277+
#if defined(__BIONIC__)
278+
// Android/FreeBSD/iOS set errno, but musl/glibc don't.
279+
EXPECT_ERRNO(EINVAL);
280+
#endif
251281
}

0 commit comments

Comments
 (0)