Merge "typo in libc/stdio/wcio.h"
diff --git a/libc/Android.mk b/libc/Android.mk
index f59fe43..dfbd57b 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -479,7 +479,8 @@
-DINET6 \
-I$(LOCAL_PATH)/private \
-DUSE_DL_PREFIX \
- -DPOSIX_MISTAKE
+ -DPOSIX_MISTAKE \
+ -DLOG_ON_HEAP_ERROR \
# these macro definitions are required to implement the
# 'timezone' and 'daylight' global variables, as well as
diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c
index 19fbb75..8c75e9c 100644
--- a/libc/bionic/dlmalloc.c
+++ b/libc/bionic/dlmalloc.c
@@ -2265,13 +2265,53 @@
#else /* PROCEED_ON_ERROR */
-#ifndef CORRUPTION_ERROR_ACTION
-#define CORRUPTION_ERROR_ACTION(m) ABORT
-#endif /* CORRUPTION_ERROR_ACTION */
+/* The following Android-specific code is used to print an informative
+ * fatal error message to the log when we detect that a heap corruption
+ * was detected. We need to be careful about not using a log function
+ * that may require an allocation here!
+ */
+#ifdef LOG_ON_HEAP_ERROR
-#ifndef USAGE_ERROR_ACTION
-#define USAGE_ERROR_ACTION(m,p) ABORT
-#endif /* USAGE_ERROR_ACTION */
+# include <private/logd.h>
+
+static void __bionic_heap_error(const char* msg, const char* function)
+{
+ /* We format the buffer explicitely, i.e. without using snprintf()
+ * which may use malloc() internally. Not something we can trust
+ * if we just detected a corrupted heap.
+ */
+ char buffer[256];
+ strlcpy(buffer, "@@@ ABORTING: ", sizeof(buffer));
+ strlcat(buffer, msg, sizeof(buffer));
+ if (function != NULL) {
+ strlcat(buffer, " IN ", sizeof(buffer));
+ strlcat(buffer, function, sizeof(buffer));
+ }
+ __libc_android_log_write(ANDROID_LOG_FATAL,"libc",buffer);
+ abort();
+}
+
+# ifndef CORRUPTION_ERROR_ACTION
+# define CORRUPTION_ERROR_ACTION(m) \
+ __bionic_heap_error("HEAP MEMORY CORRUPTION", __FUNCTION__)
+# endif
+# ifndef USAGE_ERROR_ACTION
+# define USAGE_ERROR_ACTION(m,p) \
+ __bionic_heap_error("INVALID HEAP ADDRESS", __FUNCTION__)
+# endif
+
+#else /* !LOG_ON_HEAP_ERROR */
+
+# ifndef CORRUPTION_ERROR_ACTION
+# define CORRUPTION_ERROR_ACTION(m) ABORT
+# endif /* CORRUPTION_ERROR_ACTION */
+
+# ifndef USAGE_ERROR_ACTION
+# define USAGE_ERROR_ACTION(m,p) ABORT
+# endif /* USAGE_ERROR_ACTION */
+
+#endif /* !LOG_ON_HEAP_ERROR */
+
#endif /* PROCEED_ON_ERROR */
diff --git a/libc/bionic/logd_write.c b/libc/bionic/logd_write.c
index 63dfd59..2bc39fa 100644
--- a/libc/bionic/logd_write.c
+++ b/libc/bionic/logd_write.c
@@ -48,6 +48,16 @@
#include <pthread.h>
+/* IMPORTANT IMPORTANT IMPORTANT: TECHNICAL NOTE
+ *
+ * Some of the functions below can be called when our malloc() implementation
+ * has detected that the heap is corrupted, or even from a signal handler.
+ *
+ * These functions should *not* use a function that allocates heap memory
+ * or is not signal-safe. Using direct system calls is acceptable, and we
+ * also assume that pthread_mutex_lock/unlock can be used too.
+ */
+
#define LOG_BUF_SIZE 1024
typedef enum {
@@ -77,9 +87,10 @@
{ __write_to_log_init, -1, "/dev/"LOGGER_LOG_RADIO }
};
+/* Important: see technical note at start of source file */
static int __write_to_log_null(log_id_t log_id, struct iovec *vec)
{
- /*
+ /*
* ALTERED behaviour from previous version
* always returns successful result
*/
@@ -97,23 +108,21 @@
* it's supposed, that log_id contains valid id always.
* this check must be performed in higher level functions
*/
+/* Important: see technical note at start of source file */
static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec)
{
- ssize_t ret;
-
- do {
- ret = writev(log_channels[log_id].fd, vec, 3);
- } while ((ret < 0) && (errno == EINTR));
-
- return ret;
+ return TEMP_FAILURE_RETRY( writev(log_channels[log_id].fd, vec, 3) );
}
+/* Important: see technical note at start of source file */
static int __write_to_log_init(log_id_t log_id, struct iovec *vec)
{
if ((LOG_ID_NONE < log_id) && (log_id < LOG_ID_MAX)) {
+ int fd;
+
pthread_mutex_lock(&log_init_lock);
- int fd = open(log_channels[log_id].path, O_WRONLY);
+ fd = TEMP_FAILURE_RETRY(open(log_channels[log_id].path, O_WRONLY));
log_channels[log_id].logger =
(fd < 0) ? __write_to_log_null : __write_to_log_kernel;
@@ -130,7 +139,9 @@
return -1;
}
-static int __android_log_write(int prio, const char *tag, const char *msg)
+/* Important: see technical note at start of source file */
+__LIBC_HIDDEN__
+int __libc_android_log_write(int prio, const char *tag, const char *msg)
{
struct iovec vec[3];
log_id_t log_id = LOG_ID_MAIN;
@@ -151,7 +162,11 @@
return log_channels[log_id].logger(log_id, vec);
}
-
+/* The functions below are not designed to be called from a heap panic
+ * function or from a signal handler. As such, they are free to use complex
+ * C library functions like vsnprintf()
+ */
+__LIBC_HIDDEN__
int __libc_android_log_vprint(int prio, const char *tag, const char *fmt,
va_list ap)
{
@@ -159,9 +174,10 @@
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- return __android_log_write(prio, tag, buf);
+ return __libc_android_log_write(prio, tag, buf);
}
+__LIBC_HIDDEN__
int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...)
{
va_list ap;
@@ -171,20 +187,21 @@
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
va_end(ap);
- return __android_log_write(prio, tag, buf);
+ return __libc_android_log_write(prio, tag, buf);
}
+__LIBC_HIDDEN__
int __libc_android_log_assert(const char *cond, const char *tag,
const char *fmt, ...)
{
va_list ap;
- char buf[LOG_BUF_SIZE];
+ char buf[LOG_BUF_SIZE];
va_start(ap, fmt);
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
va_end(ap);
- __android_log_write(ANDROID_LOG_FATAL, tag, buf);
+ __libc_android_log_write(ANDROID_LOG_FATAL, tag, buf);
exit(1);
diff --git a/libc/netbsd/resolv/res_cache.c b/libc/netbsd/resolv/res_cache.c
index efce7dc..20f37e1 100644
--- a/libc/netbsd/resolv/res_cache.c
+++ b/libc/netbsd/resolv/res_cache.c
@@ -1860,8 +1860,10 @@
for (i = 0; i <= MAXNS; i++) {
free(cache_info->nameservers[i]);
cache_info->nameservers[i] = NULL;
- freeaddrinfo(cache_info->nsaddrinfo[i]);
- cache_info->nsaddrinfo[i] = NULL;
+ if (cache_info->nsaddrinfo[i] != NULL) {
+ freeaddrinfo(cache_info->nsaddrinfo[i]);
+ cache_info->nsaddrinfo[i] = NULL;
+ }
}
}
diff --git a/libc/netbsd/resolv/res_state.c b/libc/netbsd/resolv/res_state.c
index 322ace9..e05846a 100644
--- a/libc/netbsd/resolv/res_state.c
+++ b/libc/netbsd/resolv/res_state.c
@@ -170,7 +170,6 @@
pthread_setspecific( _res_key, NULL );
return NULL;
}
- _resolv_cache_reset(rt->_serial);
return rt;
}
diff --git a/libc/private/logd.h b/libc/private/logd.h
index 43fa742..4a9b62e 100644
--- a/libc/private/logd.h
+++ b/libc/private/logd.h
@@ -44,6 +44,7 @@
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
};
+int __libc_android_log_write(int prio, const char* tag, const char* buffer);
int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...);
int __libc_android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap);
diff --git a/libc/unistd/open.c b/libc/unistd/open.c
index e8b1c89..03cba45 100644
--- a/libc/unistd/open.c
+++ b/libc/unistd/open.c
@@ -35,9 +35,7 @@
{
mode_t mode = 0;
-#if !defined(__i386__)
flags |= O_LARGEFILE;
-#endif
if (flags & O_CREAT)
{
diff --git a/libc/unistd/openat.c b/libc/unistd/openat.c
index 88b39a4..6b7b367 100644
--- a/libc/unistd/openat.c
+++ b/libc/unistd/openat.c
@@ -35,9 +35,7 @@
{
mode_t mode = 0;
-#if !defined(__i386__)
flags |= O_LARGEFILE;
-#endif
if (flags & O_CREAT)
{