From a115ff12999a27a4760fecf8ce1f005aa85eeb3e Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 16 Nov 2022 17:25:57 +0800 Subject: [PATCH 1/5] fix(query): fix time precision convert overflow TD-20456 --- source/common/src/ttime.c | 35 +++++++++++++++++++++-------- source/libs/function/src/builtins.c | 22 +++++++++++++++++- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/source/common/src/ttime.c b/source/common/src/ttime.c index 1b140e6c04..721c6a6053 100644 --- a/source/common/src/ttime.c +++ b/source/common/src/ttime.c @@ -436,19 +436,21 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre ASSERT(toPrecision == TSDB_TIME_PRECISION_MILLI || toPrecision == TSDB_TIME_PRECISION_MICRO || toPrecision == TSDB_TIME_PRECISION_NANO); - double tempResult = (double)utime; - switch (fromPrecision) { case TSDB_TIME_PRECISION_MILLI: { switch (toPrecision) { case TSDB_TIME_PRECISION_MILLI: return utime; case TSDB_TIME_PRECISION_MICRO: - tempResult *= 1000; + if (utime > INT64_MAX / 1000) { + return INT64_MAX; + } utime *= 1000; goto end_; case TSDB_TIME_PRECISION_NANO: - tempResult *= 1000000; + if (utime > INT64_MAX / 1000000) { + return INT64_MAX; + } utime *= 1000000; goto end_; } @@ -460,7 +462,9 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre case TSDB_TIME_PRECISION_MICRO: return utime; case TSDB_TIME_PRECISION_NANO: - tempResult *= 1000; + if (utime > INT64_MAX / 1000) { + return INT64_MAX; + } utime *= 1000; goto end_; } @@ -482,8 +486,6 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre } // end switch fromPrecision end_: - if (tempResult >= (double)INT64_MAX) return INT64_MAX; - if (tempResult <= (double)INT64_MIN) return INT64_MIN; // INT64_MIN means NULL return utime; } @@ -599,18 +601,33 @@ int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec static int32_t getDuration(int64_t val, char unit, int64_t* result, int32_t timePrecision) { switch (unit) { case 's': + if (val > INT64_MAX / MILLISECOND_PER_SECOND) { + return -1; + } (*result) = convertTimePrecision(val * MILLISECOND_PER_SECOND, TSDB_TIME_PRECISION_MILLI, timePrecision); break; case 'm': + if (val > INT64_MAX / MILLISECOND_PER_MINUTE) { + return -1; + } (*result) = convertTimePrecision(val * MILLISECOND_PER_MINUTE, TSDB_TIME_PRECISION_MILLI, timePrecision); break; case 'h': + if (val > INT64_MAX / MILLISECOND_PER_MINUTE) { + return -1; + } (*result) = convertTimePrecision(val * MILLISECOND_PER_HOUR, TSDB_TIME_PRECISION_MILLI, timePrecision); break; case 'd': + if (val > INT64_MAX / MILLISECOND_PER_DAY) { + return -1; + } (*result) = convertTimePrecision(val * MILLISECOND_PER_DAY, TSDB_TIME_PRECISION_MILLI, timePrecision); break; case 'w': + if (val > INT64_MAX / MILLISECOND_PER_WEEK) { + return -1; + } (*result) = convertTimePrecision(val * MILLISECOND_PER_WEEK, TSDB_TIME_PRECISION_MILLI, timePrecision); break; case 'a': @@ -650,7 +667,7 @@ int32_t parseAbsoluteDuration(const char* token, int32_t tokenlen, int64_t* dura /* get the basic numeric value */ int64_t timestamp = taosStr2Int64(token, &endPtr, 10); - if (errno != 0) { + if (timestamp < 0 || errno != 0) { return -1; } @@ -668,7 +685,7 @@ int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* durati /* get the basic numeric value */ *duration = taosStr2Int64(token, NULL, 10); - if (errno != 0) { + if (*duration < 0 || errno != 0) { return -1; } diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index f877bef44d..fe010786eb 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -917,6 +917,7 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err int32_t startIndex; if (numOfParams != 4) { snprintf(errMsg, msgLen, "%s", msg1); + cJSON_Delete(binDesc); return false; } @@ -928,17 +929,20 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) { snprintf(errMsg, msgLen, "%s", msg3); + cJSON_Delete(binDesc); return false; } if (count->valueint <= 0 || count->valueint > 1000) { // limit count to 1000 snprintf(errMsg, msgLen, "%s", msg4); + cJSON_Delete(binDesc); return false; } if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) || (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) { snprintf(errMsg, msgLen, "%s", msg5); + cJSON_Delete(binDesc); return false; } @@ -957,6 +961,7 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err if (width->valuedouble == 0) { snprintf(errMsg, msgLen, "%s", msg6); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } for (int i = 0; i < counter + 1; ++i) { @@ -964,6 +969,7 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err if (isinf(intervals[startIndex])) { snprintf(errMsg, msgLen, "%s", msg5); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } startIndex++; @@ -973,11 +979,13 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err if (start->valuedouble == 0) { snprintf(errMsg, msgLen, "%s", msg7); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) { snprintf(errMsg, msgLen, "%s", msg8); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } for (int i = 0; i < counter + 1; ++i) { @@ -985,6 +993,7 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err if (isinf(intervals[startIndex])) { snprintf(errMsg, msgLen, "%s", msg5); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } startIndex++; @@ -992,6 +1001,7 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err } else { snprintf(errMsg, msgLen, "%s", msg3); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } @@ -1007,6 +1017,7 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err } else if (cJSON_IsArray(binDesc)) { /* user input bins */ if (binType != USER_INPUT_BIN) { snprintf(errMsg, msgLen, "%s", msg3); + cJSON_Delete(binDesc); return false; } numOfBins = cJSON_GetArraySize(binDesc); @@ -1015,6 +1026,7 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err if (bin == NULL) { snprintf(errMsg, msgLen, "%s", msg3); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } int i = 0; @@ -1023,11 +1035,13 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err if (!cJSON_IsNumber(bin)) { snprintf(errMsg, msgLen, "%s", msg3); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } if (i != 0 && intervals[i] <= intervals[i - 1]) { snprintf(errMsg, msgLen, "%s", msg3); taosMemoryFree(intervals); + cJSON_Delete(binDesc); return false; } bin = bin->next; @@ -1035,6 +1049,7 @@ static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* err } } else { snprintf(errMsg, msgLen, "%s", msg3); + cJSON_Delete(binDesc); return false; } @@ -1464,11 +1479,16 @@ static int32_t translateDerivative(SFunctionNode* pFunc, char* pErrBuf, int32_t uint8_t colType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; // param1 - SNode* pParamNode1 = nodesListGetNode(pFunc->pParameterList, 1); + SNode* pParamNode1 = nodesListGetNode(pFunc->pParameterList, 1); + SValueNode* pValue1 = (SValueNode*)pParamNode1; if (QUERY_NODE_VALUE != nodeType(pParamNode1)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } + if (pValue1->datum.i <= 0) { + return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName); + } + SValueNode* pValue = (SValueNode*)pParamNode1; pValue->notReserved = true; From 5f6caecee0712836a4cf923f4ad31592f8c9d130 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 16 Nov 2022 17:31:34 +0800 Subject: [PATCH 2/5] unified return format --- source/common/src/ttime.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/source/common/src/ttime.c b/source/common/src/ttime.c index 721c6a6053..ecf23c91bd 100644 --- a/source/common/src/ttime.c +++ b/source/common/src/ttime.c @@ -445,14 +445,12 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre if (utime > INT64_MAX / 1000) { return INT64_MAX; } - utime *= 1000; - goto end_; + return utime * 1000; case TSDB_TIME_PRECISION_NANO: if (utime > INT64_MAX / 1000000) { return INT64_MAX; } - utime *= 1000000; - goto end_; + return utime * 1000000; } } // end from milli case TSDB_TIME_PRECISION_MICRO: { @@ -465,8 +463,7 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre if (utime > INT64_MAX / 1000) { return INT64_MAX; } - utime *= 1000; - goto end_; + return utime * 1000; } } // end from micro case TSDB_TIME_PRECISION_NANO: { From 4b9f3cd007d31c6f2f01d51ad77304508e3427e9 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 16 Nov 2022 17:31:34 +0800 Subject: [PATCH 3/5] unified return format --- source/common/src/ttime.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/common/src/ttime.c b/source/common/src/ttime.c index ecf23c91bd..66d77192bd 100644 --- a/source/common/src/ttime.c +++ b/source/common/src/ttime.c @@ -482,7 +482,6 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre } } // end switch fromPrecision -end_: return utime; } From 851888c992d7a1109084f4fd5a10868590f4d898 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 16 Nov 2022 17:31:34 +0800 Subject: [PATCH 4/5] unified return format --- source/common/src/ttime.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/common/src/ttime.c b/source/common/src/ttime.c index 66d77192bd..a106a09a69 100644 --- a/source/common/src/ttime.c +++ b/source/common/src/ttime.c @@ -451,6 +451,9 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre return INT64_MAX; } return utime * 1000000; + default: + ASSERT(0); + return utime; } } // end from milli case TSDB_TIME_PRECISION_MICRO: { @@ -464,6 +467,9 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre return INT64_MAX; } return utime * 1000; + default: + ASSERT(0); + return utime; } } // end from micro case TSDB_TIME_PRECISION_NANO: { @@ -474,10 +480,13 @@ int64_t convertTimePrecision(int64_t utime, int32_t fromPrecision, int32_t toPre return utime / 1000; case TSDB_TIME_PRECISION_NANO: return utime; + default: + ASSERT(0); + return utime; } } // end from nano default: { - assert(0); + ASSERT(0); return utime; // only to pass windows compilation } } // end switch fromPrecision From a2f3eeb6f7d69ea487115cd42b954a21e39f855f Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Thu, 17 Nov 2022 08:47:03 +0800 Subject: [PATCH 5/5] fix test cases --- tests/script/tsim/parser/function.sim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/script/tsim/parser/function.sim b/tests/script/tsim/parser/function.sim index ec9cdf2666..7f69aa2d02 100644 --- a/tests/script/tsim/parser/function.sim +++ b/tests/script/tsim/parser/function.sim @@ -821,10 +821,10 @@ sql insert into tm0 values('2015-08-18T00:18:00Z', 2.126) ('2015-08-18T00:24:00Z sql_error select derivative(ts) from tm0; sql_error select derivative(k) from tm0; -sql select derivative(k, 0, 0) from tm0; +sql_error select derivative(k, 0, 0) from tm0; sql_error select derivative(k, 1, 911) from tm0; sql_error select derivative(kx, 1s, 1) from tm0; -sql select derivative(k, -20s, 1) from tm0; +sql_error select derivative(k, -20s, 1) from tm0; sql select derivative(k, 20a, 0) from tm0; sql select derivative(k, 200a, 0) from tm0; sql select derivative(k, 999a, 0) from tm0; @@ -932,7 +932,7 @@ sql insert into t0 values('2020-1-1 1:4:10', 10); sql insert into t1 values('2020-1-1 1:1:2', 2); print ===========================>td-4739 -sql select diff(val) from (select derivative(k, 1s, 0) val from t1); +sql select diff(val) from (select ts, derivative(k, 1s, 0) val from t1); if $rows != 0 then return -1 endi @@ -1077,4 +1077,4 @@ endi if $data11 != NULL then print ======data11=$data11 return -1 -endi \ No newline at end of file +endi