Merge pull request #6857 from taosdata/feature/TD-5169
[TD-5169]<fix>: fixed a potential crash bug
This commit is contained in:
commit
b8e8046716
|
@ -395,6 +395,8 @@ int32_t* taosGetErrno();
|
||||||
#define TSDB_CODE_HTTP_OP_VALUE_NULL TAOS_DEF_ERROR_CODE(0, 0x11A5) //"value not find")
|
#define TSDB_CODE_HTTP_OP_VALUE_NULL TAOS_DEF_ERROR_CODE(0, 0x11A5) //"value not find")
|
||||||
#define TSDB_CODE_HTTP_OP_VALUE_TYPE TAOS_DEF_ERROR_CODE(0, 0x11A6) //"value type should be boolean number or string")
|
#define TSDB_CODE_HTTP_OP_VALUE_TYPE TAOS_DEF_ERROR_CODE(0, 0x11A6) //"value type should be boolean number or string")
|
||||||
|
|
||||||
|
#define TSDB_CODE_HTTP_REQUEST_JSON_ERROR TAOS_DEF_ERROR_CODE(0, 0x1F00) //"http request json error")
|
||||||
|
|
||||||
// odbc
|
// odbc
|
||||||
#define TSDB_CODE_ODBC_OOM TAOS_DEF_ERROR_CODE(0, 0x2100) //"out of memory")
|
#define TSDB_CODE_ODBC_OOM TAOS_DEF_ERROR_CODE(0, 0x2100) //"out of memory")
|
||||||
#define TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM TAOS_DEF_ERROR_CODE(0, 0x2101) //"convertion not a valid literal input")
|
#define TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM TAOS_DEF_ERROR_CODE(0, 0x2101) //"convertion not a valid literal input")
|
||||||
|
|
|
@ -35,4 +35,7 @@ void httpTrimTableName(char *name);
|
||||||
int32_t httpShrinkTableName(HttpContext *pContext, int32_t pos, char *name);
|
int32_t httpShrinkTableName(HttpContext *pContext, int32_t pos, char *name);
|
||||||
char * httpGetCmdsString(HttpContext *pContext, int32_t pos);
|
char * httpGetCmdsString(HttpContext *pContext, int32_t pos);
|
||||||
|
|
||||||
|
int32_t httpCheckAllocEscapeSql(char *oldSql, char **newSql);
|
||||||
|
void httpCheckFreeEscapedSql(char *oldSql, char *newSql);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -176,6 +176,16 @@ bool gcProcessQueryRequest(HttpContext* pContext) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ESCAPE_ERROR_PROC(code, context, root) \
|
||||||
|
do { \
|
||||||
|
if (code != TSDB_CODE_SUCCESS) { \
|
||||||
|
httpSendErrorResp(context, code); \
|
||||||
|
\
|
||||||
|
cJSON_Delete(root); \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
for (int32_t i = 0; i < size; ++i) {
|
for (int32_t i = 0; i < size; ++i) {
|
||||||
cJSON* query = cJSON_GetArrayItem(root, i);
|
cJSON* query = cJSON_GetArrayItem(root, i);
|
||||||
if (query == NULL) continue;
|
if (query == NULL) continue;
|
||||||
|
@ -186,7 +196,14 @@ bool gcProcessQueryRequest(HttpContext* pContext) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t refIdBuffer = httpAddToSqlCmdBuffer(pContext, refId->valuestring);
|
char *newStr = NULL;
|
||||||
|
int32_t retCode = 0;
|
||||||
|
|
||||||
|
retCode = httpCheckAllocEscapeSql(refId->valuestring, &newStr);
|
||||||
|
ESCAPE_ERROR_PROC(retCode, pContext, root);
|
||||||
|
|
||||||
|
int32_t refIdBuffer = httpAddToSqlCmdBuffer(pContext, newStr);
|
||||||
|
httpCheckFreeEscapedSql(refId->valuestring, newStr);
|
||||||
if (refIdBuffer == -1) {
|
if (refIdBuffer == -1) {
|
||||||
httpWarn("context:%p, fd:%d, user:%s, refId buffer is full", pContext, pContext->fd, pContext->user);
|
httpWarn("context:%p, fd:%d, user:%s, refId buffer is full", pContext, pContext->fd, pContext->user);
|
||||||
break;
|
break;
|
||||||
|
@ -195,7 +212,11 @@ bool gcProcessQueryRequest(HttpContext* pContext) {
|
||||||
cJSON* alias = cJSON_GetObjectItem(query, "alias");
|
cJSON* alias = cJSON_GetObjectItem(query, "alias");
|
||||||
int32_t aliasBuffer = -1;
|
int32_t aliasBuffer = -1;
|
||||||
if (!(alias == NULL || alias->valuestring == NULL || strlen(alias->valuestring) == 0)) {
|
if (!(alias == NULL || alias->valuestring == NULL || strlen(alias->valuestring) == 0)) {
|
||||||
aliasBuffer = httpAddToSqlCmdBuffer(pContext, alias->valuestring);
|
retCode = httpCheckAllocEscapeSql(alias->valuestring, &newStr);
|
||||||
|
ESCAPE_ERROR_PROC(retCode, pContext, root);
|
||||||
|
|
||||||
|
aliasBuffer = httpAddToSqlCmdBuffer(pContext, newStr);
|
||||||
|
httpCheckFreeEscapedSql(alias->valuestring, newStr);
|
||||||
if (aliasBuffer == -1) {
|
if (aliasBuffer == -1) {
|
||||||
httpWarn("context:%p, fd:%d, user:%s, alias buffer is full", pContext, pContext->fd, pContext->user);
|
httpWarn("context:%p, fd:%d, user:%s, alias buffer is full", pContext, pContext->fd, pContext->user);
|
||||||
break;
|
break;
|
||||||
|
@ -211,7 +232,11 @@ bool gcProcessQueryRequest(HttpContext* pContext) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t sqlBuffer = httpAddToSqlCmdBuffer(pContext, sql->valuestring);
|
retCode = httpCheckAllocEscapeSql(sql->valuestring, &newStr);
|
||||||
|
ESCAPE_ERROR_PROC(retCode, pContext, root);
|
||||||
|
|
||||||
|
int32_t sqlBuffer = httpAddToSqlCmdBuffer(pContext, newStr);
|
||||||
|
httpCheckFreeEscapedSql(sql->valuestring, newStr);
|
||||||
if (sqlBuffer == -1) {
|
if (sqlBuffer == -1) {
|
||||||
httpWarn("context:%p, fd:%d, user:%s, sql buffer is full", pContext, pContext->fd, pContext->user);
|
httpWarn("context:%p, fd:%d, user:%s, sql buffer is full", pContext, pContext->fd, pContext->user);
|
||||||
break;
|
break;
|
||||||
|
@ -237,6 +262,8 @@ bool gcProcessQueryRequest(HttpContext* pContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef ESCAPE_ERROR_PROC
|
||||||
|
|
||||||
pContext->reqType = HTTP_REQTYPE_MULTI_SQL;
|
pContext->reqType = HTTP_REQTYPE_MULTI_SQL;
|
||||||
pContext->encodeMethod = &gcQueryMethod;
|
pContext->encodeMethod = &gcQueryMethod;
|
||||||
pContext->multiCmds->pos = 0;
|
pContext->multiCmds->pos = 0;
|
||||||
|
|
|
@ -423,3 +423,65 @@ void httpProcessRequest(HttpContext *pContext) {
|
||||||
httpExecCmd(pContext);
|
httpExecCmd(pContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t httpCheckAllocEscapeSql(char *oldSql, char **newSql)
|
||||||
|
{
|
||||||
|
char *pos;
|
||||||
|
|
||||||
|
if (oldSql == NULL || newSql == NULL) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bad sql clause */
|
||||||
|
pos = strstr(oldSql, "%%");
|
||||||
|
if (pos) {
|
||||||
|
httpError("bad sql:%s", oldSql);
|
||||||
|
return TSDB_CODE_HTTP_REQUEST_JSON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = strchr(oldSql, '%');
|
||||||
|
if (pos == NULL) {
|
||||||
|
httpDebug("sql:%s", oldSql);
|
||||||
|
*newSql = oldSql;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
*newSql = (char *) calloc(1, (strlen(oldSql) << 1) + 1);
|
||||||
|
if (newSql == NULL) {
|
||||||
|
httpError("failed to allocate for new sql, old sql:%s", oldSql);
|
||||||
|
return TSDB_CODE_HTTP_NO_ENOUGH_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *src = oldSql;
|
||||||
|
char *dst = *newSql;
|
||||||
|
size_t sqlLen = strlen(src);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
memcpy(dst, src, pos - src + 1);
|
||||||
|
dst += pos - src + 1;
|
||||||
|
*dst++ = '%';
|
||||||
|
|
||||||
|
if (pos + 1 >= oldSql + sqlLen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = ++pos;
|
||||||
|
pos = strchr(pos, '%');
|
||||||
|
if (pos == NULL) {
|
||||||
|
memcpy(dst, src, strlen(src));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void httpCheckFreeEscapedSql(char *oldSql, char *newSql)
|
||||||
|
{
|
||||||
|
if (oldSql && newSql) {
|
||||||
|
if (oldSql != newSql) {
|
||||||
|
free(newSql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -610,7 +610,18 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) {
|
||||||
// stable tag for detail
|
// stable tag for detail
|
||||||
for (int32_t i = 0; i < orderTagsLen; ++i) {
|
for (int32_t i = 0; i < orderTagsLen; ++i) {
|
||||||
cJSON *tag = orderedTags[i];
|
cJSON *tag = orderedTags[i];
|
||||||
stable_cmd->tagNames[i] = table_cmd->tagNames[i] = httpAddToSqlCmdBuffer(pContext, tag->string);
|
|
||||||
|
char *tagStr = NULL;
|
||||||
|
int32_t retCode = httpCheckAllocEscapeSql(tag->string, &tagStr);
|
||||||
|
if (retCode != TSDB_CODE_SUCCESS) {
|
||||||
|
httpSendErrorResp(pContext, retCode);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stable_cmd->tagNames[i] = table_cmd->tagNames[i] = httpAddToSqlCmdBuffer(pContext, tagStr);
|
||||||
|
|
||||||
|
httpCheckFreeEscapedSql(tag->string, tagStr);
|
||||||
|
|
||||||
if (tag->type == cJSON_String)
|
if (tag->type == cJSON_String)
|
||||||
stable_cmd->tagValues[i] = table_cmd->tagValues[i] = httpAddToSqlCmdBuffer(pContext, "'%s'", tag->valuestring);
|
stable_cmd->tagValues[i] = table_cmd->tagValues[i] = httpAddToSqlCmdBuffer(pContext, "'%s'", tag->valuestring);
|
||||||
|
|
|
@ -403,6 +403,8 @@ TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_VALUE_TOO_LONG, "tag value can not mor
|
||||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_NULL, "value not find")
|
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_NULL, "value not find")
|
||||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_TYPE, "value type should be boolean, number or string")
|
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_TYPE, "value type should be boolean, number or string")
|
||||||
|
|
||||||
|
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_REQUEST_JSON_ERROR, "http request json error")
|
||||||
|
|
||||||
// odbc
|
// odbc
|
||||||
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, "out of memory")
|
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, "out of memory")
|
||||||
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, "convertion not a valid literal input")
|
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, "convertion not a valid literal input")
|
||||||
|
|
|
@ -247,4 +247,25 @@ if $system_content != @[{"refId":"A","target":"{val1:nil, val2:nil}","datapoints
|
||||||
return -1
|
return -1
|
||||||
endi
|
endi
|
||||||
|
|
||||||
|
sql create table tt (ts timestamp ,i int) tags(j binary(20),k binary(20));
|
||||||
|
sql insert into t1 using tt tags('jnetworki','t1') values('2020-01-01 00:00:00.000',1)('2020-01-01 00:01:00.000',2)('2020-01-01 00:02:00.000',3)('2020-01-01 00:03:00.000',4)('2020-01-01 00:04:00.000',5);
|
||||||
|
|
||||||
|
system_content curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d '[ {"refId":"A","alias":"","sql":"select max(i) from db.tt where j like \u0027%network%\u0027 and ts >= \u00272020-01-01 00:00:00.000\u0027 and ts < \u00272020-01-01 00:05:00.000\u0027 interval(5m) group by k "} ]' 127.0.0.1:7111/grafana/query
|
||||||
|
print step1-> $system_content
|
||||||
|
if $system_content != @[{"refId":"A","target":"{k:t1}","datapoints":[[5,1577808000000]]}]@ then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
|
||||||
|
system_content curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d '[ {"refId":"A","alias":"","sql":"select max(i) from db.tt where j like \u0027jnetwo%\u0027 and ts >= \u00272020-01-01 00:00:00.000\u0027 and ts < \u00272020-01-01 00:05:00.000\u0027 interval(5m) group by k "} ]' 127.0.0.1:7111/grafana/query
|
||||||
|
print step1-> $system_content
|
||||||
|
if $system_content != @[{"refId":"A","target":"{k:t1}","datapoints":[[5,1577808000000]]}]@ then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
|
||||||
|
system_content curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d '[ {"refId":"A","alias":"","sql":"select max(i) from db.tt where j like \u0027%networki\u0027 and ts >= \u00272020-01-01 00:00:00.000\u0027 and ts < \u00272020-01-01 00:05:00.000\u0027 interval(5m) group by k "} ]' 127.0.0.1:7111/grafana/query
|
||||||
|
print step1-> $system_content
|
||||||
|
if $system_content != @[{"refId":"A","target":"{k:t1}","datapoints":[[5,1577808000000]]}]@ then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
|
||||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
Loading…
Reference in New Issue