Merge "Fix 'adb shell /system/bin/linker' crash"
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index b57e242..d0172ed 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -230,7 +230,6 @@
/* Perform formatted output to an output target 'o' */
template <typename Out>
static void out_vformat(Out& o, const char* format, va_list args) {
- int caller_errno = errno;
int nn = 0;
for (;;) {
@@ -379,9 +378,6 @@
} else if (c == '%') {
buffer[0] = '%';
buffer[1] = '\0';
- } else if (c == 'm') {
- // syslog-like %m for strerror(errno).
- str = strerror(caller_errno);
} else {
__assert(__FILE__, __LINE__, "conversion specifier unsupported");
}
diff --git a/libc/bionic/syslog.cpp b/libc/bionic/syslog.cpp
index 29f892a..d8b8b19 100644
--- a/libc/bionic/syslog.cpp
+++ b/libc/bionic/syslog.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <errno.h>
#include <stdlib.h>
#include <syslog.h>
@@ -47,6 +48,8 @@
}
void vsyslog(int priority, const char* fmt, va_list args) {
+ int caller_errno = errno;
+
// Check whether we're supposed to be logging messages of this priority.
if ((syslog_priority_mask & LOG_MASK(LOG_PRI(priority))) == 0) {
return;
@@ -71,5 +74,48 @@
android_log_priority = ANDROID_LOG_DEBUG;
}
- __libc_format_log_va_list(android_log_priority, log_tag, fmt, args);
+ // glibc's printf family support %m directly, but our BSD-based one doesn't.
+ // If the format string seems to contain "%m", rewrite it.
+ const char* log_fmt = fmt;
+ if (strstr(fmt, "%m") != NULL) {
+ size_t dst_len = 1024;
+ char* dst = reinterpret_cast<char*>(malloc(dst_len));
+ log_fmt = dst;
+
+ const char* src = fmt;
+ for (; dst_len > 0 && *src != '\0'; ++src) {
+ if (*src == '%' && *(src + 1) == 'm') {
+ // Expand %m.
+ size_t n = strlcpy(dst, strerror(caller_errno), dst_len);
+ if (n >= dst_len) {
+ n = dst_len;
+ }
+ dst += n;
+ dst_len -= n;
+ ++src;
+ } else if (*src == '%' && *(src + 1) == '%') {
+ // We need to copy pairs of '%'s so the %m test works.
+ if (dst_len <= 2) {
+ break;
+ }
+ *dst++ = '%'; --dst_len;
+ *dst++ = '%'; --dst_len;
+ ++src;
+ } else {
+ *dst++ = *src; --dst_len;
+ }
+ }
+ *dst = '\0';
+ }
+
+ // We can't let __libc_format_log do the formatting because it doesn't support
+ // all the printf functionality.
+ char log_line[1024];
+ vsnprintf(log_line, sizeof(log_line), log_fmt, args);
+
+ if (log_fmt != fmt) {
+ free(const_cast<char*>(log_fmt));
+ }
+
+ __libc_format_log(android_log_priority, log_tag, "%s", log_line);
}
diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h
index a44b2e5..34a29df 100644
--- a/libc/include/sys/syscall.h
+++ b/libc/include/sys/syscall.h
@@ -37,7 +37,7 @@
__BEGIN_DECLS
-int syscall(int number, ...);
+long syscall(long number, ...);
__END_DECLS
diff --git a/tests/libc_logging_test.cpp b/tests/libc_logging_test.cpp
index ef39d1c..950161e 100644
--- a/tests/libc_logging_test.cpp
+++ b/tests/libc_logging_test.cpp
@@ -176,14 +176,3 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif // __BIONIC__
}
-
-TEST(libc_logging, m) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- errno = EBADF;
- __libc_format_buffer(buf, sizeof(buf), "<%m>");
- EXPECT_STREQ("<Bad file number>", buf);
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 58c9ad9..2a65657 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/syscall.h>
@@ -212,6 +213,14 @@
ASSERT_EQ(EBADF, errno);
}
+TEST(unistd, syscall_long) {
+ // Check that syscall(3) correctly returns long results.
+ // https://code.google.com/p/android/issues/detail?id=73952
+ // We assume that the break is > 4GiB, but this is potentially flaky.
+ uintptr_t p = reinterpret_cast<uintptr_t>(sbrk(0));
+ ASSERT_EQ(p, static_cast<uintptr_t>(syscall(__NR_brk, 0)));
+}
+
TEST(unistd, alarm) {
ASSERT_EQ(0U, alarm(0));
}