Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21 #1108

Closed
Satsukina opened this issue Oct 25, 2019 · 16 comments
Assignees
Labels
Projects

Comments

@Satsukina
Copy link

Description

use mbstowcs to convert multibyte to widechar and use wcstombs to convert back. But these two functions' return value are always 0 and convert fail.

example 1:
char *buffer = "1234";
int length = mbstowcs(NULL, buffer, 0);

The return value length is 0, its expected value should be 4.

example 2:
wchar_t *buffer = L"1234";
int length = wcstombs(NULL, buffer, 0);

The return value length is 0, its expected value should be 4.

Environment Details

Not all of these will be relevant to every bug, but please provide as much
information as you can.

  • NDK Version: 20.0.5594570
  • Build system: ndk-build
  • Host OS: Windows
  • ABI: armeabi-v7a, x86
  • NDK API level: 16
  • Device API level: 17
@Satsukina Satsukina added the bug label Oct 25, 2019
@DanAlbert
Copy link
Member

Yeah, the implementation back then ignores a line from POSIX:

If pwcs is a null pointer, mbstowcs() shall return the length required to convert the entire array regardless of the value of n

This is already fixed in new devices. The only way to fix it for old devices is to make it a part of libandroid_support so that it's statically linked into everything. This comes pretty close to what we explicitly decided against over in #456.

This was fixed as of L (https://android-review.googlesource.com/c/platform/bionic/+/92730).

@enh-google wdyt? The workaround here is trivial (just pass strlen(buffer) + 1 instead of 0), so I'm not sure if we should impose that cost on every app. If we wanted to help users avoid this we could even have a fortify check on these pre-L that causes an error if you call this with a null dest ptr and a 0 length.

@rprichard
Copy link
Collaborator

The pre-L libc functions I looked at seem to treat wchar_t as being one byte in size, whereas it's always 4 bytes in the NDK. e.g.:

  • printf("%ls\n", L"hello") ==> prints "h" in JB (prints "hello" in L)
  • printf("%ls\n", (const wchar_t*)"hello") ==> prints "hello" in JB (prints nothing or crashes in L)
  • mbstowcs(NULL, "\xce\x91" "\xce\x91" "\xce\x91", 256) ==> returns 7 in JB (returns 3 in L)
  • wcstombs(NULL, L"123456789", 256) ==> returns 2 in JB (returns 9 in L)

The last example shows another problem -- pre-L mbstowcs/wcstombs return the size of their input strings plus 1. (I guess they're counting the NUL terminator?)

@Satsukina
Copy link
Author

@DanAlbert Thanks for your reply. But just like @rprichard said, function's return values are different between JB and L. And if i try to use mbstowcs to convert a Chinese string, the converted string is incorrect in JB.

@enh-google
Copy link
Collaborator

given how broken these are pre-L it does seem like we should either change the #ifs so you don't get them if you're targeting earlier, or we should add them to the support library. right now we don't even document that they're broken pre-L :-(

@DanAlbert DanAlbert added this to the r23 milestone Apr 11, 2020
@DanAlbert
Copy link
Member

(if someone else wants to take this we can probably move to r22, but I think I'm already being overly optimistic about the number of things I've planned for myself in r22)

@DanAlbert DanAlbert added this to Triaged in r23 Jul 7, 2020
@DanAlbert DanAlbert removed this from the r23 milestone Jan 8, 2021
@DanAlbert DanAlbert removed this from Triaged in r23 Jun 10, 2021
@DanAlbert DanAlbert added this to Triaged in r24 via automation Jun 10, 2021
@enh-google
Copy link
Collaborator

we talked about this internally last month but never wrote down what we said, so here's my attempt to recap...

it looks like we have two main choices here:

  1. stop declaring these for pre-L in the headers (and libc.map.txt) because they're broken. quick and easy, but not super helpful to anyone, and might break libc++ (because we're still on an older version that doesn't cope gracefully with attempts to say using ::something_not_defined;).
  2. add this to libandroid_support.

it seems like we decided against 2, but i'm no longer sure why, and coming to this "fresh" (i.e. a month later so i don't remember all the details), 2 sounds like the better idea? especially because we already went so far down that route. look at ndk/sources/android/support/Android.mk:

android_support_sources := \
    $(BIONIC_PATH)/libc/bionic/c32rtomb.cpp \
    $(BIONIC_PATH)/libc/bionic/locale.cpp \
    $(BIONIC_PATH)/libc/bionic/mbrtoc32.cpp \
    $(BIONIC_PATH)/libc/bionic/wchar.cpp \
    $(BIONIC_PATH)/libc/upstream-openbsd/lib/libc/locale/mbtowc.c \
    src/locale_support.cpp \
    src/swprintf.cpp \
    src/wcstox.cpp \

it's all wide char stuff at this point. so it seems weird to miss out a couple of extra functions? (especially when one of the still-broken functions is mbstowcs() and we already added the single-character equivalent mbtowc()?)

a quick look suggests that both bionic/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c and bionic/libc/upstream-openbsd/lib/libc/locale/wcstombs.c seem fine to include in libandroid_support?

@DanAlbert
Copy link
Member

Re-reading that thread, I think those were intended as two steps rather than alternatives. Agreed with all your reasoning :)

@enh-google
Copy link
Collaborator

oh, so you're thinking:

  1. add this to libandroid_support, roughly as described under 2 above, and also modify the bionic headers so if you compile without libandroid_support you don't get these two (broken) functions?

@DanAlbert
Copy link
Member

That seems to be our best option, yeah.

@rprichard
Copy link
Collaborator

Should we remove other broken wide char functions from headers and libc.map.txt? e.g. wcstol, wcstod, wprintf

It looks like wchar_t became 4 bytes starting with Gingerbread, so some of the simplest wide char functions probably work correctly on old devices (e.g. wcscpy, wcsncpy, wcscat, wcslen, wcschr). libandroid_support doesn't have wcscpy, but it does have wcsncpy and the other functions I listed that AFAIK aren't necessary.

@DanAlbert
Copy link
Member

Should we remove other broken wide char functions from headers and libc.map.txt? e.g. wcstol, wcstod, wprintf

Assuming you mean bump the introduction version to 21 where they start working, +1. We're not doing anyone any favors advertising support for broken APIs.

@enh-google
Copy link
Collaborator

Should we remove other broken wide char functions from headers and libc.map.txt? e.g. wcstol, wcstod, wprintf

doesn't ndk/sources/android/support/src/wcstox.cpp fix all the wcsto* functions?

wprintf() seems legitimately broken, but personally i'm happy ignoring anything we haven't explicitly had a bug report about... there's definitely a risk of removing something broken and breaking apps because they were compiling and/or linking against it, but not actually using it.

if mbstowcs() and wcstombs() are the only functions we've had bug reports for in 5+ years, that's probably all we actually need to worry about. especially since we shouldn't be too far off API 21 as the lowest supported API. i assume anyone supporting API < 21 in 2021 has an old app that "works", not anyone writing new code.

JarlPenguin pushed a commit to AOSP-on-montana/platform_bionic that referenced this issue Nov 12, 2021
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
@DanAlbert DanAlbert moved this from Triaged to Needs cherry-pick in r24 Nov 19, 2021
@DanAlbert DanAlbert moved this from Needs cherry-pick to Triaged in r24 Dec 9, 2021
@DanAlbert
Copy link
Member

There's still a little bit more work to do here. I had to flag a few tests as broken because although theses are backported in libandroid_support, the headers don't reflect that: https://android-review.googlesource.com/c/platform/ndk/+/1915003

I'm not sure what the best fix to this is. We can either remove the guard entirely (leading to a subpar diagnostic for C builds that don't use libandroid_support), or we could probably redeclare the APIs in the libandroid_support headers and lean on #pragma GCC system_header to suppress any redecl warnings (leading to a subpar diagnostic for C++ builds that don't use libandroid_support). There are probably other options too but those two are the ones that come to mind quickly.

@enh-google
Copy link
Collaborator

We can either remove the guard entirely (leading to a subpar diagnostic for C builds that don't use libandroid_support)

devil's advocate man asks: "now that libandroid_support isn't terrible, should we revisit that and just always have libandroid_support, and not make it a libc++ thing?"

@DanAlbert DanAlbert added this to Triaged in r25 via automation Jan 4, 2022
@DanAlbert DanAlbert removed this from Triaged in r24 Jan 4, 2022
@DanAlbert
Copy link
Member

DanAlbert commented Jan 4, 2022

As fixed as this is going to get in r24 (works correctly now, UX not perfect for the expected-failing cases). Moving the cleanup work to r25.

unicornx pushed a commit to aosp-riscv/platform-ndk that referenced this issue Jan 7, 2022
The sysroot update broke this test because it calls mbstowcs/wcstombs
but libc (correctly) marks it as unavailable before API 21. However
libandroid_support backports this API so it is actually safe to call
here and the error should not be omitted.

I'm not sure if the best fix here is to lie in libc (I think that's
what we do for other APIs like this) or to redefine the availability
in the libandroid_support header and pragma away the redefinition
warning. In the interest of time we'll just need to xfail the test for
r24 beta 2 though.

Test: ./run_tests.py --rebuild
Bug: android/ndk#1108
Change-Id: Ie5e2f5b8dfbd8cd33925bd0ad4615cee5e555613
unicornx pushed a commit to aosp-riscv/platform-ndk that referenced this issue Jan 7, 2022
Same as the prior commit, just the other flavor of this test.

Test: ./run_tests.py --rebuild (but without a filter this time)
Bug: android/ndk#1108
Change-Id: I69e2d4d4f0a7255c8d14ca85681764c14732a71e
@DanAlbert DanAlbert removed this from Triaged in r25 Jan 10, 2022
ziasam pushed a commit to Project-Zephyrus/android_bionic that referenced this issue May 28, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
Signed-off-by: DennySPb <dennyspb@gmail.com>
ziasam pushed a commit to Project-Zephyrus/android_bionic that referenced this issue May 28, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
Signed-off-by: DennySPb <dennyspb@gmail.com>
Khalvat-M pushed a commit to LineageOS-UL/android_bionic that referenced this issue May 29, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
Khalvat-M pushed a commit to LineageOS-UL/android_bionic that referenced this issue May 29, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
shutter-cat pushed a commit to VoltageOS/bionic that referenced this issue May 29, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
Signed-off-by: Dmitrii <bankersenator@gmail.com>
shutter-cat pushed a commit to VoltageOS/bionic that referenced this issue May 29, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
Signed-off-by: Dmitrii <bankersenator@gmail.com>
HyperN00B pushed a commit to CrystalOS-Temp/bionic that referenced this issue May 31, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
HyperN00B pushed a commit to CrystalOS-Temp/bionic that referenced this issue May 31, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
HyperN00B pushed a commit to CrystalOS-Temp/bionic that referenced this issue Jun 7, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
HyperN00B pushed a commit to CrystalOS-Temp/bionic that referenced this issue Jun 7, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
travarilo pushed a commit to bananadroid/android_bionic that referenced this issue Jul 8, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
travarilo pushed a commit to bananadroid/android_bionic that referenced this issue Jul 8, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
travarilo pushed a commit to bananadroid/android_bionic that referenced this issue Jul 14, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
travarilo pushed a commit to bananadroid/android_bionic that referenced this issue Jul 14, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
travarilo pushed a commit to bananadroid/android_bionic that referenced this issue Aug 3, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
travarilo pushed a commit to bananadroid/android_bionic that referenced this issue Aug 3, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
BayerischeMotorenWerke pushed a commit to BayerischeMotorenWerke/android_bionic that referenced this issue Aug 12, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
BayerischeMotorenWerke pushed a commit to BayerischeMotorenWerke/android_bionic that referenced this issue Aug 12, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
HyperN00B pushed a commit to CrystalOS-Temp/bionic that referenced this issue Sep 5, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
HyperN00B pushed a commit to CrystalOS-Temp/bionic that referenced this issue Sep 5, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
eldainosor pushed a commit to Bootleggers-BrokenLab/bionic that referenced this issue Sep 17, 2022
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
Signed-off-by: DennySPb <dennyspb@gmail.com>
eldainosor pushed a commit to Bootleggers-BrokenLab/bionic that referenced this issue Sep 17, 2022
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
Signed-off-by: DennySPb <dennyspb@gmail.com>
melles1991 pushed a commit to ExodusOS/android_bionic that referenced this issue Jan 7, 2023
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
melles1991 pushed a commit to ExodusOS/android_bionic that referenced this issue Jan 7, 2023
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
melles1991 pushed a commit to ExodusOS/android_bionic that referenced this issue Jan 8, 2023
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
melles1991 pushed a commit to ExodusOS/android_bionic that referenced this issue Jan 8, 2023
Definitions for these are provided in libandroid_support for API
levels that do not expose this in the stubs. For the rare cases where
libandroid_support is not being used this will result in a lower
quality diagnostic (undefined reference instead of "not available
until API 21"), but other fixes would also have that behavior because
the libandroid_support headers are *always* available, even if
libandroid_support won't be linked.

Test: Reverted xfailed tests for #1108 and reran tests with this
Bug: android/ndk#1108
Change-Id: I371f5b9d7caeef8dc7c80f2f6d11280ecba119c9
mgood7123 added a commit to mgood7123/llvm_18 that referenced this issue Mar 10, 2024
sepehrst pushed a commit to spsforks/android-bionic-libc that referenced this issue Apr 22, 2024
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
sepehrst pushed a commit to spsforks/android-bionic-libc that referenced this issue Apr 22, 2024
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem.

Test: None
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
sepehrst pushed a commit to spsforks/android-bionic-libc that referenced this issue Apr 22, 2024
Mbstowcs and wcstombs cannot get correct return value when called in the environment below api 21, and need to raise the API level to solve the problem. Also, the test for mbstowcs should be included.

Test: added test
fix bug 1108 android/ndk#1108

Change-Id: Iabcf1bff0be087288646687732ef68870630b48a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
No open projects
r24
  
Merged
Development

No branches or pull requests

5 participants