From d52edb75bbe392fc24f317dabbe4e69245ae993d Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Fri, 8 Sep 2017 16:47:44 +0200 Subject: Bug#23072792 MYSQL_GROUP_SUFFIX DOES NOT WORK Reintroduce environment variable MYSQL_GROUP_SUFFIX to be used as --default-group-suffix value if not already set. The environment variable was accidentally renamed to DEFAULT_GROUP_SUFFIX_ENV in MySQL server 5.5. --- mysys/default.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mysys') diff --git a/mysys/default.c b/mysys/default.c index 6fe00af087e..75274f25edf 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -234,7 +234,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, (char **) &my_defaults_group_suffix); if (! my_defaults_group_suffix) - my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV)); + my_defaults_group_suffix= getenv("MYSQL_GROUP_SUFFIX"); if (forced_extra_defaults && !defaults_already_read) { -- cgit v1.2.1 From d8001106c97db246b33b977c09986beea22941bb Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 15 Jan 2018 01:34:26 +0100 Subject: MDEV-14469 build with cmake -DMYSQL_MAINTAINER_MODE=ON fails: 'readdir_r' is deprecated 1. test readdir_r() availability under -Werror 2. don't protect readdir() with mutexes, it's not needed for the way we use readdir() --- mysys/my_lib.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'mysys') diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 71969f23d85..08ff6a94823 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -103,10 +103,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DBUG_ENTER("my_dir"); DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags)); -#if !defined(HAVE_READDIR_R) - mysql_mutex_lock(&THR_LOCK_open); -#endif - dirp = opendir(directory_file_name(tmp_path,(char *) path)); #if defined(__amiga__) if ((dirp->dd_fd) < 0) /* Directory doesn't exists */ @@ -162,9 +158,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags) } (void) closedir(dirp); -#if !defined(HAVE_READDIR_R) - mysql_mutex_unlock(&THR_LOCK_open); -#endif result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; result->number_off_files= dir_entries_storage->elements; @@ -174,9 +167,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DBUG_RETURN(result); error: -#if !defined(HAVE_READDIR_R) - mysql_mutex_unlock(&THR_LOCK_open); -#endif my_errno=errno; if (dirp) (void) closedir(dirp); -- cgit v1.2.1 From 26e5f9dda13efad33e867742ea4e42e479b51b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 Jan 2018 22:57:52 +0200 Subject: MDEV-14229: Stack trace is not resolved for shared objects Resolving a stacktrace including functions in dynamic libraries requires us to look inside the libraries for the symbols. Addr2line needs to be started with the correct binary for each address on the stack. To do this, figure out which library it is using dladdr, then if the addr2line binary was started with a different binary, fork it again with the correct one. We only have one addr2line process running at any point during the stacktrace resolving step. The maximum number of forks for addr2line should generally be around 6. One for server stacktrace code, one for plugin code, one when going back into server code, one for pthread library, one for libc, one for the _start function in the server. More can come up if plugin calls server function which goes back to a plugin, etc. --- mysys/CMakeLists.txt | 2 +- mysys/my_addr_resolve.c | 97 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 32 deletions(-) (limited to 'mysys') diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index cb86850c2de..15f3fbad9bf 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -67,7 +67,7 @@ ENDIF() ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES}) TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARY} - ${LIBNSL} ${LIBM} ${LIBRT} ${LIBSOCKET} ${LIBEXECINFO}) + ${LIBNSL} ${LIBM} ${LIBRT} ${LIBSOCKET} ${LIBEXECINFO} ${LIBDL}) DTRACE_INSTRUMENT(mysys) IF(HAVE_BFD_H) diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 90e6f43f390..f831ad5121f 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -132,15 +132,79 @@ err: #include #include + +#include + static int in[2], out[2]; -static int initialized= 0; +static pid_t pid; +static char addr2line_binary[1024]; static char output[1024]; + +int start_addr2line_fork(const char *binary_path) +{ + + if (pid > 0) + { + /* Don't leak FDs */ + close(in[1]); + close(out[0]); + /* Don't create zombie processes. */ + waitpid(pid, NULL, 0); + } + + if (pipe(in) < 0) + return 1; + if (pipe(out) < 0) + return 1; + + pid = fork(); + if (pid == -1) + return 1; + + if (!pid) /* child */ + { + dup2(in[0], 0); + dup2(out[1], 1); + close(in[0]); + close(in[1]); + close(out[0]); + close(out[1]); + execlp("addr2line", "addr2line", "-C", "-f", "-e", binary_path, NULL); + exit(1); + } + + close(in[0]); + close(out[1]); + + return 0; +} + int my_addr_resolve(void *ptr, my_addr_loc *loc) { char input[32], *s; size_t len; - len= my_snprintf(input, sizeof(input), "%p\n", ptr); + Dl_info info; + void *offset; + + if (!dladdr(ptr, &info)) + return 1; + + if (strcmp(addr2line_binary, info.dli_fname)) + { + /* We use dli_fname in case the path is longer than the length of our static + string. We don't want to allocate anything dynamicaly here as we are in + a "crashed" state. */ + if (start_addr2line_fork(info.dli_fname)) + { + addr2line_binary[0] = '\0'; + return 1; + } + /* Save result for future comparisons. */ + strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); + } + offset = info.dli_fbase; + len= my_snprintf(input, sizeof(input), "%p\n", ptr - offset); if (write(in[1], input, len) <= 0) return 1; if (read(out[0], output, sizeof(output)) <= 0) @@ -168,35 +232,6 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) const char *my_addr_resolve_init() { - if (!initialized) - { - pid_t pid; - - if (pipe(in) < 0) - return "pipe(in)"; - if (pipe(out) < 0) - return "pipe(out)"; - - pid = fork(); - if (pid == -1) - return "fork"; - - if (!pid) /* child */ - { - dup2(in[0], 0); - dup2(out[1], 1); - close(in[0]); - close(in[1]); - close(out[0]); - close(out[1]); - execlp("addr2line", "addr2line", "-C", "-f", "-e", my_progname, NULL); - exit(1); - } - - close(in[0]); - close(out[1]); - initialized= 1; - } return 0; } #endif -- cgit v1.2.1 From 22ae3843db6c8b2a84ca5d16cd99025abb52cc27 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 20 Jan 2018 17:59:11 +0100 Subject: Correct TRASH() macro usage TRASH was mapped to TRASH_FREE and was supposed to be used for memory that should not be accessed anymore, while TRASH_ALLOC() is to be used for uninitialized but to-be-used memory. But sometimes TRASH() was used in the latter sense. Remove TRASH() macro, always use explicit TRASH_ALLOC() or TRASH_FREE(). --- mysys/my_alloc.c | 2 +- mysys/my_thr_init.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'mysys') diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 1054db6cee4..d7bc4247556 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -293,7 +293,7 @@ void *multi_alloc_root(MEM_ROOT *root, ...) DBUG_RETURN((void*) start); } -#define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left) +#define TRASH_MEM(X) TRASH_FREE(((char*)(X) + ((X)->size-(X)->left)), (X)->left) /* Mark all data in blocks free for reusage */ diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index aefd3564185..55ee1db657e 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -423,8 +423,6 @@ void my_thread_end(void) if (--THR_thread_count == 0) mysql_cond_signal(&THR_COND_threads); mysql_mutex_unlock(&THR_LOCK_threads); - - TRASH(tmp, sizeof(*tmp)); free(tmp); } } -- cgit v1.2.1 From dc28b6d180a00658debf65b1258bd5fdf0d0c26e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2018 12:53:17 +0100 Subject: improve ASAN instrumentation: MEM_ROOT more complete TRASH-ing of memroots --- mysys/my_alloc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'mysys') diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index d7bc4247556..24e95d2c69c 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -22,6 +22,8 @@ #undef EXTRA_DEBUG #define EXTRA_DEBUG +#define TRASH_MEM(X) TRASH_FREE(((char*)(X) + ((X)->size-(X)->left)), (X)->left) + /* Initialize memory root @@ -60,12 +62,13 @@ void init_alloc_root(MEM_ROOT *mem_root, size_t block_size, if (pre_alloc_size) { if ((mem_root->free= mem_root->pre_alloc= - (USED_MEM*) my_malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)), + (USED_MEM*) my_malloc(pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)), MYF(0)))) { mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM)); mem_root->free->left= pre_alloc_size; mem_root->free->next= 0; + TRASH_MEM(mem_root->free); } } #endif @@ -132,6 +135,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, mem->left= pre_alloc_size; mem->next= *prev; *prev= mem_root->pre_alloc= mem; + TRASH_MEM(mem); } else { @@ -225,6 +229,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) next->size= get_size; next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); *prev=next; + TRASH_MEM(next); } point= (uchar*) ((char*) next+ (next->size-next->left)); @@ -293,8 +298,6 @@ void *multi_alloc_root(MEM_ROOT *root, ...) DBUG_RETURN((void*) start); } -#define TRASH_MEM(X) TRASH_FREE(((char*)(X) + ((X)->size-(X)->left)), (X)->left) - /* Mark all data in blocks free for reusage */ static inline void mark_blocks_free(MEM_ROOT* root) -- cgit v1.2.1 From a4663af05c1d1bd3abb537205df070ed2158e702 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 22 Jan 2018 16:53:10 +0100 Subject: MDEV-7533: COLUMN_JSON() doesn't escape control characters in string values escape all charecters less or equal 0x1F (control symbols) (shorter sequence are not used to make code simple, long encoding is always legal according to the rfc4627) --- mysys/ma_dyncol.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) (limited to 'mysys') diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index 9f6df107316..0c54bd7a581 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -3819,6 +3819,58 @@ end: DBUG_RETURN(rc); } +static +my_bool dynstr_append_json_quoted(DYNAMIC_STRING *str, + const char *append, size_t len) +{ + uint additional= ((str->alloc_increment && str->alloc_increment > 6) ? + str->alloc_increment : + 10); + uint lim= additional; + uint i; + if (dynstr_realloc(str, len + additional + 2)) + return TRUE; + str->str[str->length++]= '"'; + for (i= 0; i < len; i++) + { + register char c= append[i]; + if (unlikely(c <= 0x1F)) + { + if (lim < 5) + { + if (dynstr_realloc(str, additional)) + return TRUE; + lim+= additional; + } + lim-= 5; + str->str[str->length++]= '\\'; + str->str[str->length++]= 'u'; + str->str[str->length++]= '0'; + str->str[str->length++]= '0'; + str->str[str->length++]= (c < 0x10 ? '0' : '1'); + c%= 0x10; + str->str[str->length++]= (c < 0xA ? '0' + c : 'A' + (c - 0xA)); + } + else + { + if (c == '"' || c == '\\') + { + if (!lim) + { + if (dynstr_realloc(str, additional)) + return TRUE; + lim= additional; + } + lim--; + str->str[str->length++]= '\\'; + } + str->str[str->length++]= c; + } + } + str->str[str->length++]= '"'; + return FALSE; +} + enum enum_dyncol_func_result mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val, @@ -3884,7 +3936,10 @@ mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val, return ER_DYNCOL_RESOURCE; } if (quote) - rc= dynstr_append_quoted(str, from, len, quote); + if (quote == DYNCOL_JSON_ESC) + rc= dynstr_append_json_quoted(str, from, len); + else + rc= dynstr_append_quoted(str, from, len, quote); else rc= dynstr_append_mem(str, from, len); if (alloc) @@ -4184,7 +4239,8 @@ mariadb_dyncol_json_internal(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json, } else { - if ((rc= mariadb_dyncol_val_str(json, &val, DYNCOL_UTF, '"')) < 0) + if ((rc= mariadb_dyncol_val_str(json, &val, DYNCOL_UTF, DYNCOL_JSON_ESC)) + < 0) goto err; } } -- cgit v1.2.1 From 7a63ffab71644118223aefe66094366a7b7f115e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 29 Jan 2018 18:56:08 +0200 Subject: Fix an out of scope bzero --- mysys/mf_iocache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mysys') diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 31a09e214d2..bd71e2ae527 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -258,7 +258,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, else { /* Clear mutex so that safe_mutex will notice that it's not initialized */ - bzero((char*) &info->append_buffer_lock, sizeof(info)); + bzero((char*) &info->append_buffer_lock, sizeof(info->append_buffer_lock)); } #endif -- cgit v1.2.1 From 29031fe391d53f6befcd55737539af477c447a9d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 2 Feb 2018 11:41:16 +0100 Subject: my_addr_resolve fixes * use a longer timeout, 10ms is not always enough * stop waiting as long as the data is read, do not unconditionally wait for timeout every time --- mysys/my_addr_resolve.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'mysys') diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index e9685985660..82043dc03fe 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -186,13 +186,13 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ssize_t total_bytes_read = 0; ssize_t extra_bytes_read = 0; + ssize_t parsed = 0; fd_set set; struct timeval timeout; int filename_start = -1; int line_number_start = -1; - ssize_t i; Dl_info info; void *offset; @@ -221,11 +221,12 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) FD_ZERO(&set); FD_SET(out[0], &set); - /* 10 ms should be plenty of time for addr2line to issue a response. */ + /* 100 ms should be plenty of time for addr2line to issue a response. */ timeout.tv_sec = 0; - timeout.tv_usec = 10000; + timeout.tv_usec = 100000; /* Read in a loop till all the output from addr2line is complete. */ - while (select(out[0] + 1, &set, NULL, NULL, &timeout) > 0) + while (parsed == total_bytes_read && + select(out[0] + 1, &set, NULL, NULL, &timeout) > 0) { extra_bytes_read= read(out[0], output + total_bytes_read, sizeof(output) - total_bytes_read); @@ -236,35 +237,33 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) break; total_bytes_read += extra_bytes_read; - } - - /* Failed starting addr2line. */ - if (total_bytes_read == 0) - return 1; - /* Go through the addr2line response and get the required data. - The response is structured in 2 lines. The first line contains the function - name, while the second one contains : */ - for (i = 0; i < total_bytes_read; i++) { - if (output[i] == '\n') { - filename_start = i + 1; - output[i] = '\0'; - } - if (filename_start != -1 && output[i] == ':') { - line_number_start = i + 1; - output[i] = '\0'; - } - if (line_number_start != -1) { - loc->line= atoi(output + line_number_start); - break; + /* Go through the addr2line response and get the required data. + The response is structured in 2 lines. The first line contains the function + name, while the second one contains : */ + for (; parsed < total_bytes_read; parsed++) + { + if (output[parsed] == '\n') + { + filename_start = parsed + 1; + output[parsed] = '\0'; + } + if (filename_start != -1 && output[parsed] == ':') + { + line_number_start = parsed + 1; + output[parsed] = '\0'; + break; + } } } + /* Response is malformed. */ if (filename_start == -1 || line_number_start == -1) return 1; loc->func= output; loc->file= output + filename_start; + loc->line= atoi(output + line_number_start); /* Addr2line was unable to extract any meaningful information. */ if (strcmp(loc->file, "??") == 0) -- cgit v1.2.1 From b6455479e588fe1309157e8cc77cca10b90942b6 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 7 Feb 2018 18:14:45 +0100 Subject: MDEV-15230: column_json breaks cyrillic in 10.1.31 Use unsigned comparison. --- mysys/ma_dyncol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mysys') diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index 0c54bd7a581..909f9dcac41 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -3834,7 +3834,7 @@ my_bool dynstr_append_json_quoted(DYNAMIC_STRING *str, for (i= 0; i < len; i++) { register char c= append[i]; - if (unlikely(c <= 0x1F)) + if (unlikely(((uchar)c) <= 0x1F)) { if (lim < 5) { -- cgit v1.2.1 From 60dfe12be3adaa03a8d409ca2da58e78e6d0c972 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 7 Feb 2018 18:54:11 +0100 Subject: MDEV-14868 MariaDB server crashes after using ROLLBACK TO when encrypt_tmp_files=ON Fix reinit_io_cache(WRITE_CACHE) with non-zero seek_offset. Run encryption.tempfiles with and without binlog checksums. --- mysys/mf_iocache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mysys') diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index a0ddc3e40a5..56b1ae3fc6e 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -440,7 +440,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, info->read_end= info->buffer; _my_b_encr_read(info, 0, 0); /* prefill the buffer */ info->write_pos= info->read_pos; - info->pos_in_file+= info->buffer_length; + info->seek_not_done=1; } } else -- cgit v1.2.1