Merge "Make apex availability of some bionic libraries explicit" into main
diff --git a/libc/bionic/strtol.cpp b/libc/bionic/strtol.cpp
index 05b4b53..def7921 100644
--- a/libc/bionic/strtol.cpp
+++ b/libc/bionic/strtol.cpp
@@ -35,141 +35,88 @@
#include <wchar.h>
template <typename T, T Min, T Max, typename CharT>
-T StrToI(const CharT* nptr, CharT** endptr, int base) {
+__attribute__((always_inline)) T StrToI(const CharT* s, CharT** end_ptr, int base) {
// Ensure that base is between 2 and 36 inclusive, or the special value of 0.
if (base < 0 || base == 1 || base > 36) {
- if (endptr != nullptr) *endptr = const_cast<CharT*>(nptr);
+ if (end_ptr != nullptr) *end_ptr = const_cast<CharT*>(s);
errno = EINVAL;
return 0;
}
// Skip white space and pick up leading +/- sign if any.
- // If base is 0, allow 0x for hex and 0 for octal, else
- // assume decimal; if base is already 16, allow 0x.
- const CharT* s = nptr;
+ const CharT* p = s;
int c;
- do {
- c = *s++;
- } while (isspace(c));
- int neg;
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else {
- neg = 0;
- if (c == '+') c = *s++;
+ while (isspace(c = *p++)) {
}
- if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X') && isxdigit(s[1])) {
- c = s[1];
- s += 2;
+ bool neg = false;
+ if (c == '-') {
+ neg = true;
+ c = *p++;
+ } else if (c == '+') {
+ c = *p++;
+ }
+
+ // If base is 0 or 16, allow "0x" prefix for hex.
+ if ((base == 0 || base == 16) && c == '0' && (*p == 'x' || *p == 'X') && isxdigit(p[1])) {
+ c = p[1];
+ p += 2;
base = 16;
}
- if ((base == 0 || base == 2) && c == '0' && (*s == 'b' || *s == 'B') && isdigit(s[1])) {
- c = s[1];
- s += 2;
+ // If base is 0 or 2, allow "0b" prefix for binary.
+ if ((base == 0 || base == 2) && c == '0' && (*p == 'b' || *p == 'B') && isdigit(p[1])) {
+ c = p[1];
+ p += 2;
base = 2;
}
+ // If base is 0, allow "0" prefix for octal, otherwise base is 10.
if (base == 0) base = (c == '0') ? 8 : 10;
- // We always work in the negative space because the most negative value has a
- // larger magnitude than the most positive value.
- T cutoff = Min / base;
- int cutlim = -(Min % base);
+ constexpr bool is_signed = (Min != 0);
+ T acc = 0;
// Non-zero if any digits consumed; negative to indicate overflow/underflow.
int any = 0;
- T acc = 0;
- for (; ; c = *s++) {
+ for (;; c = *p++) {
if (isdigit(c)) {
c -= '0';
} else if (isalpha(c)) {
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ c = 10 + (_tolower(c) - 'a');
} else {
break;
}
if (c >= base) break;
if (any < 0) continue;
- if (acc < cutoff || (acc == cutoff && c > cutlim)) {
- any = -1;
- acc = Min;
- errno = ERANGE;
+ if (is_signed) {
+ // We work in the negative space because the most negative value has a
+ // larger magnitude than the most positive value.
+ if (__builtin_mul_overflow(acc, base, &acc) || __builtin_sub_overflow(acc, c, &acc)) {
+ any = -1;
+ continue;
+ }
} else {
- any = 1;
- acc *= base;
- acc -= c;
+ if (__builtin_mul_overflow(acc, base, &acc) || __builtin_add_overflow(acc, c, &acc)) {
+ any = -1;
+ continue;
+ }
}
- }
- if (endptr != nullptr) *endptr = const_cast<CharT*>(any ? s - 1 : nptr);
- if (!neg) {
- if (acc == Min) {
- errno = ERANGE;
- acc = Max;
- } else {
- acc = -acc;
- }
- }
- return acc;
-}
-
-template <typename T, T Max, typename CharT>
-T StrToU(const CharT* nptr, CharT** endptr, int base) {
- if (base < 0 || base == 1 || base > 36) {
- if (endptr != nullptr) *endptr = const_cast<CharT*>(nptr);
- errno = EINVAL;
- return 0;
+ any = 1;
}
- const CharT* s = nptr;
- int c;
- do {
- c = *s++;
- } while (isspace(c));
- int neg;
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else {
- neg = 0;
- if (c == '+') c = *s++;
- }
- if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X') && isxdigit(s[1])) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if ((base == 0 || base == 2) && c == '0' && (*s == 'b' || *s == 'B') && isdigit(s[1])) {
- c = s[1];
- s += 2;
- base = 2;
- }
- if (base == 0) base = (c == '0') ? 8 : 10;
+ if (end_ptr != nullptr) *end_ptr = const_cast<CharT*>(any ? p - 1 : s);
- T cutoff = Max / static_cast<T>(base);
- int cutlim = Max % static_cast<T>(base);
- T acc = 0;
- int any = 0;
- for (; ; c = *s++) {
- if (isdigit(c)) {
- c -= '0';
- } else if (isalpha(c)) {
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- } else {
- break;
- }
- if (c >= base) break;
- if (any < 0) continue;
- if (acc > cutoff || (acc == cutoff && c > cutlim)) {
- any = -1;
- acc = Max;
- errno = ERANGE;
- } else {
- any = 1;
- acc *= base;
- acc += c;
- }
+ // Detected overflow/underflow in the loop?
+ if (any == -1) {
+ errno = ERANGE;
+ return (is_signed && neg) ? Min : Max;
}
- if (neg && any > 0) acc = -acc;
- if (endptr != nullptr) *endptr = const_cast<CharT*>(any ? s - 1 : nptr);
- return acc;
+
+ // Will we overflow by trying to negate the most negative value?
+ if (any > 0 && is_signed && !neg && acc == Min) {
+ errno = ERANGE;
+ return Max;
+ }
+
+ if (is_signed) return neg ? acc : -acc;
+ return neg ? -acc : acc;
}
int atoi(const char* s) {
@@ -209,25 +156,25 @@
}
unsigned long strtoul(const char* s, char** end, int base) {
- return StrToU<unsigned long, ULONG_MAX, char>(s, end, base);
+ return StrToI<unsigned long, 0, ULONG_MAX, char>(s, end, base);
}
unsigned long wcstoul(const wchar_t* s, wchar_t** end, int base) {
- return StrToU<unsigned long, ULONG_MAX, wchar_t>(s, end, base);
+ return StrToI<unsigned long, 0, ULONG_MAX, wchar_t>(s, end, base);
}
unsigned long long strtoull(const char* s, char** end, int base) {
- return StrToU<unsigned long long, ULLONG_MAX, char>(s, end, base);
+ return StrToI<unsigned long long, 0, ULLONG_MAX, char>(s, end, base);
}
unsigned long long wcstoull(const wchar_t* s, wchar_t** end, int base) {
- return StrToU<unsigned long long, ULLONG_MAX, wchar_t>(s, end, base);
+ return StrToI<unsigned long long, 0, ULLONG_MAX, wchar_t>(s, end, base);
}
uintmax_t strtoumax(const char* s, char** end, int base) {
- return StrToU<uintmax_t, UINTMAX_MAX, char>(s, end, base);
+ return StrToI<uintmax_t, 0, UINTMAX_MAX, char>(s, end, base);
}
uintmax_t wcstoumax(const wchar_t* s, wchar_t** end, int base) {
- return StrToU<uintmax_t, UINTMAX_MAX, wchar_t>(s, end, base);
+ return StrToI<uintmax_t, 0, UINTMAX_MAX, wchar_t>(s, end, base);
}
diff --git a/libc/system_properties/prop_area.cpp b/libc/system_properties/prop_area.cpp
index d5693b9..4668eed 100644
--- a/libc/system_properties/prop_area.cpp
+++ b/libc/system_properties/prop_area.cpp
@@ -41,7 +41,7 @@
#include <async_safe/log.h>
-constexpr size_t PA_SIZE = 256 * 1024;
+constexpr size_t PA_SIZE = 128 * 1024;
constexpr uint32_t PROP_AREA_MAGIC = 0x504f5250;
constexpr uint32_t PROP_AREA_VERSION = 0xfc6ed0ab;
diff --git a/tests/sys_hwprobe_test.cpp b/tests/sys_hwprobe_test.cpp
index 3c8dce2..6b74e18 100644
--- a/tests/sys_hwprobe_test.cpp
+++ b/tests/sys_hwprobe_test.cpp
@@ -41,19 +41,10 @@
EXPECT_EQ(RISCV_HWPROBE_KEY_IMA_EXT_0, probes[0].key);
EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_IMA_FD) != 0);
EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_IMA_C) != 0);
- // TODO: remove #define when our uapi headers are new enough.
-#define RISCV_HWPROBE_IMA_V (1 << 2)
EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_IMA_V) != 0);
- // TODO: remove #ifs when our kernel is new enough.
-#if defined(RISCV_HWPROBE_EXT_ZBA)
EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_EXT_ZBA) != 0);
-#endif
-#if defined(RISCV_HWPROBE_EXT_ZBB)
EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_EXT_ZBB) != 0);
-#endif
-#if defined(RISCV_HWPROBE_EXT_ZBS)
EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_EXT_ZBS) != 0);
-#endif
EXPECT_EQ(RISCV_HWPROBE_KEY_CPUPERF_0, probes[1].key);
EXPECT_TRUE((probes[1].value & RISCV_HWPROBE_MISALIGNED_MASK) == RISCV_HWPROBE_MISALIGNED_FAST);
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index dff92ea..0b7f5ae 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -593,7 +593,7 @@
ASSERT_TRUE(system_properties.valid());
auto name = "ro.super_long_property"s;
- auto value = std::string(256 * 1024 + 1, 'x');
+ auto value = std::string(128 * 1024 + 1, 'x');
ASSERT_NE(0, system_properties.Add(name.c_str(), name.size(), value.c_str(), value.size()));
#else // __BIONIC__