From 73eee9d80bde3dcde35d75f9437fda73b4d1f383 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Thu, 28 May 2020 15:25:56 +0800 Subject: [PATCH 1/2] fix possible dead loop in shellPrintNChar --- src/kit/shell/inc/shell.h | 1 - src/kit/shell/src/shellDarwin.c | 25 -------------------- src/kit/shell/src/shellEngine.c | 39 +++++++++++++++++++++++++++++--- src/kit/shell/src/shellLinux.c | 24 -------------------- src/kit/shell/src/shellWindows.c | 26 --------------------- 5 files changed, 36 insertions(+), 79 deletions(-) diff --git a/src/kit/shell/inc/shell.h b/src/kit/shell/inc/shell.h index 5400d9c5ba..54ac45583c 100644 --- a/src/kit/shell/inc/shell.h +++ b/src/kit/shell/inc/shell.h @@ -68,7 +68,6 @@ void get_history_path(char* history); void cleanup_handler(void* arg); void exitShell(); int shellDumpResult(TAOS* con, char* fname, int* error_no, bool printMode); -void shellPrintNChar(const char* str, int length, int width); void shellGetGrantInfo(void *con); int isCommentLine(char *line); diff --git a/src/kit/shell/src/shellDarwin.c b/src/kit/shell/src/shellDarwin.c index 987087d71f..98ea6510d7 100644 --- a/src/kit/shell/src/shellDarwin.c +++ b/src/kit/shell/src/shellDarwin.c @@ -349,31 +349,6 @@ void *shellLoopQuery(void *arg) { return NULL; } -void shellPrintNChar(const char *str, int length, int width) { - int pos = 0, cols = 0; - while (pos < length) { - wchar_t wc; - pos += mbtowc(&wc, str + pos, MB_CUR_MAX); - if (pos > length) { - break; - } - - int w = wcwidth(wc); - if (w > 0) { - if (width > 0 && cols + w > width) { - break; - } - printf("%lc", wc); - cols += w; - } - } - - for (; cols < width; cols++) { - putchar(' '); - } -} - - int get_old_terminal_mode(struct termios *tio) { /* Make sure stdin is a terminal. */ if (!isatty(STDIN_FILENO)) { diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index 4ef51eaa5a..5b4da875de 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -435,7 +435,6 @@ static int dumpResultToFile(const char* fname, TAOS_RES* result) { int num_fields = taos_num_fields(result); TAOS_FIELD *fields = taos_fetch_fields(result); - int32_t* length = taos_fetch_lengths(result); int precision = taos_result_precision(result); for (int col = 0; col < num_fields; col++) { @@ -448,6 +447,7 @@ static int dumpResultToFile(const char* fname, TAOS_RES* result) { int numOfRows = 0; do { + int32_t* length = taos_fetch_lengths(result); for (int i = 0; i < num_fields; i++) { if (i > 0) { fputc(',', fp); @@ -465,6 +465,39 @@ static int dumpResultToFile(const char* fname, TAOS_RES* result) { } +static void shellPrintNChar(const char *str, int length, int width) { + int pos = 0, cols = 0; + while (pos < length) { + wchar_t wc; + int bytes = mbtowc(&wc, str + pos, MB_CUR_MAX); + if (bytes == 0) { + break; + } + pos += bytes; + if (pos > length) { + break; + } + +#ifdef WINDOWS + int w = bytes; +#else + int w = wcwidth(wc); +#endif + if (w > 0) { + if (width > 0 && cols + w > width) { + break; + } + printf("%lc", wc); + cols += w; + } + } + + for (; cols < width; cols++) { + putchar(' '); + } +} + + static void printField(const char* val, TAOS_FIELD* field, int width, int32_t length, int precision) { if (val == NULL) { int w = width; @@ -523,7 +556,6 @@ static int verticalPrintResult(TAOS_RES* result) { int num_fields = taos_num_fields(result); TAOS_FIELD *fields = taos_fetch_fields(result); - int32_t* length = taos_fetch_lengths(result); int precision = taos_result_precision(result); int maxColNameLen = 0; @@ -537,6 +569,7 @@ static int verticalPrintResult(TAOS_RES* result) { int numOfRows = 0; do { printf("*************************** %d.row ***************************\n", numOfRows + 1); + int32_t* length = taos_fetch_lengths(result); for (int i = 0; i < num_fields; i++) { TAOS_FIELD* field = fields + i; @@ -631,7 +664,6 @@ static int horizontalPrintResult(TAOS_RES* result) { int num_fields = taos_num_fields(result); TAOS_FIELD *fields = taos_fetch_fields(result); - int32_t* length = taos_fetch_lengths(result); int precision = taos_result_precision(result); int width[TSDB_MAX_COLUMNS]; @@ -643,6 +675,7 @@ static int horizontalPrintResult(TAOS_RES* result) { int numOfRows = 0; do { + int32_t* length = taos_fetch_lengths(result); for (int i = 0; i < num_fields; i++) { putchar(' '); printField(row[i], fields + i, width[i], length[i], precision); diff --git a/src/kit/shell/src/shellLinux.c b/src/kit/shell/src/shellLinux.c index d8b3e9bb4d..b4b74eae3a 100644 --- a/src/kit/shell/src/shellLinux.c +++ b/src/kit/shell/src/shellLinux.c @@ -323,30 +323,6 @@ void *shellLoopQuery(void *arg) { return NULL; } -void shellPrintNChar(const char *str, int length, int width) { - int pos = 0, cols = 0; - while (pos < length) { - wchar_t wc; - pos += mbtowc(&wc, str + pos, MB_CUR_MAX); - if (pos > length) { - break; - } - - int w = wcwidth(wc); - if (w > 0) { - if (width > 0 && cols + w > width) { - break; - } - printf("%lc", wc); - cols += w; - } - } - - for (; cols < width; cols++) { - putchar(' '); - } -} - int get_old_terminal_mode(struct termios *tio) { /* Make sure stdin is a terminal. */ if (!isatty(STDIN_FILENO)) { diff --git a/src/kit/shell/src/shellWindows.c b/src/kit/shell/src/shellWindows.c index 440aa508ab..48545f537e 100644 --- a/src/kit/shell/src/shellWindows.c +++ b/src/kit/shell/src/shellWindows.c @@ -214,32 +214,6 @@ void *shellLoopQuery(void *arg) { return NULL; } -void shellPrintNChar(const char *str, int length, int width) { - int pos = 0, cols = 0; - while (pos < length) { - wchar_t wc; - int bytes = mbtowc(&wc, str + pos, MB_CUR_MAX); - pos += bytes; - if (pos > length) { - break; - } - - int w = bytes; - if (w > 0) { - if (width > 0 && cols + w > width) { - break; - } - printf("%lc", wc); - cols += w; - } - } - - for (; cols < width; cols++) { - putchar(' '); - } -} - - void get_history_path(char *history) { sprintf(history, "%s/%s", ".", HISTORY_FILE); } void exitShell() { exit(EXIT_SUCCESS); } From 8c49afc1f47ddc5cd00e2f42ff13964d7e85dbf8 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Thu, 28 May 2020 16:15:24 +0800 Subject: [PATCH 2/2] fix incorrect length in nchar conversion --- src/client/src/tscSubquery.c | 5 ++++- src/util/inc/tutil.h | 2 +- src/util/src/tutil.c | 16 ++++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index 3a205924bf..8c741dfdc8 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -1888,11 +1888,14 @@ static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pF /* string terminated char for binary data*/ memset(pRes->buffer[columnIndex], 0, pField->bytes + TSDB_NCHAR_SIZE); - if (taosUcs4ToMbs(pRes->tsrow[columnIndex], pField->bytes - VARSTR_HEADER_SIZE, pRes->buffer[columnIndex])) { + int32_t length = taosUcs4ToMbs(pRes->tsrow[columnIndex], pRes->length[columnIndex], pRes->buffer[columnIndex]); + if ( length >= 0 ) { pRes->tsrow[columnIndex] = pRes->buffer[columnIndex]; + pRes->length[columnIndex] = length; } else { tscError("%p charset:%s to %s. val:%ls convert failed.", pSql, DEFAULT_UNICODE_ENCODEC, tsCharset, pRes->tsrow[columnIndex]); pRes->tsrow[columnIndex] = NULL; + pRes->length[columnIndex] = 0; } } } diff --git a/src/util/inc/tutil.h b/src/util/inc/tutil.h index 3a0a1920af..5dcb6e406f 100644 --- a/src/util/inc/tutil.h +++ b/src/util/inc/tutil.h @@ -145,7 +145,7 @@ bool taosMbsToUcs4(char *mbs, size_t mbs_len, char *ucs4, int32_t ucs4_max_len, int tasoUcs4Compare(void* f1_ucs4, void *f2_ucs4, int bytes); -bool taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs); +int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs); bool taosValidateEncodec(const char *encodec); diff --git a/src/util/src/tutil.c b/src/util/src/tutil.c index 989273e051..2392560370 100644 --- a/src/util/src/tutil.c +++ b/src/util/src/tutil.c @@ -447,10 +447,10 @@ int tasoUcs4Compare(void* f1_ucs4, void *f2_ucs4, int bytes) { int32_t ucs4_max_len = bytes + 4; char *f1_mbs = calloc(bytes, 1); char *f2_mbs = calloc(bytes, 1); - if (!taosUcs4ToMbs(f1_ucs4, ucs4_max_len, f1_mbs)) { + if (taosUcs4ToMbs(f1_ucs4, ucs4_max_len, f1_mbs) < 0) { return -1; } - if (!taosUcs4ToMbs(f2_ucs4, ucs4_max_len, f2_mbs)) { + if (taosUcs4ToMbs(f2_ucs4, ucs4_max_len, f2_mbs) < 0) { return -1; } int32_t ret = strcmp(f1_mbs, f2_mbs); @@ -464,29 +464,29 @@ int tasoUcs4Compare(void* f1_ucs4, void *f2_ucs4, int bytes) { #endif } -bool taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs) { +int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs) { #ifdef USE_LIBICONV iconv_t cd = iconv_open(tsCharset, DEFAULT_UNICODE_ENCODEC); size_t ucs4_input_len = ucs4_max_len; size_t outLen = ucs4_max_len; if (iconv(cd, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) { iconv_close(cd); - return false; + return -1; } iconv_close(cd); - return true; + return (int32_t)(ucs4_max_len - outLen); #else mbstate_t state = {0}; int32_t len = (int32_t) wcsnrtombs(NULL, (const wchar_t **) &ucs4, ucs4_max_len / 4, 0, &state); if (len < 0) { - return false; + return -1; } memset(&state, 0, sizeof(state)); len = wcsnrtombs(mbs, (const wchar_t **) &ucs4, ucs4_max_len / 4, (size_t) len, &state); if (len < 0) { - return false; + return -1; } - return true; + return len; #endif }