提交 88f0d2c8 编写于 作者: B Bomin Zhang

TD-459: fix some strncpy

上级 1e7fd87d
...@@ -795,7 +795,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) { ...@@ -795,7 +795,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) {
STableMetaInfo *pSTableMeterMetaInfo = tscGetMetaInfo(pQueryInfo, STABLE_INDEX); STableMetaInfo *pSTableMeterMetaInfo = tscGetMetaInfo(pQueryInfo, STABLE_INDEX);
tscSetTableFullName(pSTableMeterMetaInfo, &sToken, pSql); tscSetTableFullName(pSTableMeterMetaInfo, &sToken, pSql);
strncpy(pTag->name, pSTableMeterMetaInfo->name, TSDB_TABLE_ID_LEN); tstrncpy(pTag->name, pSTableMeterMetaInfo->name, sizeof(pTag->name));
code = tscGetTableMeta(pSql, pSTableMeterMetaInfo); code = tscGetTableMeta(pSql, pSTableMeterMetaInfo);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
return code; return code;
...@@ -989,7 +989,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) { ...@@ -989,7 +989,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) {
int validateTableName(char *tblName, int len) { int validateTableName(char *tblName, int len) {
char buf[TSDB_TABLE_ID_LEN] = {0}; char buf[TSDB_TABLE_ID_LEN] = {0};
strncpy(buf, tblName, len); tstrncpy(buf, tblName, sizeof(buf));
SSQLToken token = {.n = len, .type = TK_ID, .z = buf}; SSQLToken token = {.n = len, .type = TK_ID, .z = buf};
tSQLGetToken(buf, &token.type); tSQLGetToken(buf, &token.type);
...@@ -1512,7 +1512,7 @@ void tscProcessMultiVnodesInsertFromFile(SSqlObj *pSql) { ...@@ -1512,7 +1512,7 @@ void tscProcessMultiVnodesInsertFromFile(SSqlObj *pSql) {
} }
pCmd->count = 1; pCmd->count = 1;
strncpy(path, pDataBlock->filename, PATH_MAX); tstrncpy(path, pDataBlock->filename, sizeof(path));
FILE *fp = fopen(path, "r"); FILE *fp = fopen(path, "r");
if (fp == NULL) { if (fp == NULL) {
...@@ -1520,7 +1520,7 @@ void tscProcessMultiVnodesInsertFromFile(SSqlObj *pSql) { ...@@ -1520,7 +1520,7 @@ void tscProcessMultiVnodesInsertFromFile(SSqlObj *pSql) {
continue; continue;
} }
strncpy(pTableMetaInfo->name, pDataBlock->tableId, TSDB_TABLE_ID_LEN); tstrncpy(pTableMetaInfo->name, pDataBlock->tableId, sizeof(pTableMetaInfo->name));
memset(pDataBlock->pData, 0, pDataBlock->nAllocSize); memset(pDataBlock->pData, 0, pDataBlock->nAllocSize);
int32_t ret = tscGetTableMeta(pSql, pTableMetaInfo); int32_t ret = tscGetTableMeta(pSql, pTableMetaInfo);
......
...@@ -239,8 +239,7 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) { ...@@ -239,8 +239,7 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
continue; continue;
} }
strncpy(pQdesc->sql, pSql->sqlstr, TSDB_SHOW_SQL_LEN - 1); tstrncpy(pQdesc->sql, pSql->sqlstr, sizeof(pQdesc->sql));
pQdesc->sql[TSDB_SHOW_SQL_LEN - 1] = 0;
pQdesc->stime = htobe64(pSql->stime); pQdesc->stime = htobe64(pSql->stime);
pQdesc->queryId = htonl(pSql->queryId); pQdesc->queryId = htonl(pSql->queryId);
pQdesc->useconds = htobe64(pSql->res.useconds); pQdesc->useconds = htobe64(pSql->res.useconds);
...@@ -256,8 +255,7 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) { ...@@ -256,8 +255,7 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
SSqlStream *pStream = pObj->streamList; SSqlStream *pStream = pObj->streamList;
while (pStream) { while (pStream) {
strncpy(pSdesc->sql, pStream->pSql->sqlstr, TSDB_SHOW_SQL_LEN - 1); tstrncpy(pSdesc->sql, pStream->pSql->sqlstr, sizeof(pSdesc->sql));
pSdesc->sql[TSDB_SHOW_SQL_LEN - 1] = 0;
pSdesc->streamId = htonl(pStream->streamId); pSdesc->streamId = htonl(pStream->streamId);
pSdesc->num = htobe64(pStream->num); pSdesc->num = htobe64(pStream->num);
......
...@@ -1309,7 +1309,7 @@ static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumn ...@@ -1309,7 +1309,7 @@ static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumn
SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex); SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex);
char* colName = (pItem->aliasName == NULL) ? pSchema->name : pItem->aliasName; char* colName = (pItem->aliasName == NULL) ? pSchema->name : pItem->aliasName;
strncpy(pExpr->aliasName, colName, tListLen(pExpr->aliasName)); tstrncpy(pExpr->aliasName, colName, sizeof(pExpr->aliasName));
SColumnList ids = {0}; SColumnList ids = {0};
ids.num = 1; ids.num = 1;
...@@ -1359,7 +1359,7 @@ static int32_t doAddProjectionExprAndResultFields(SQueryInfo* pQueryInfo, SColum ...@@ -1359,7 +1359,7 @@ static int32_t doAddProjectionExprAndResultFields(SQueryInfo* pQueryInfo, SColum
for (int32_t j = 0; j < numOfTotalColumns; ++j) { for (int32_t j = 0; j < numOfTotalColumns; ++j) {
SSqlExpr* pExpr = doAddProjectCol(pQueryInfo, startPos + j, j, pIndex->tableIndex); SSqlExpr* pExpr = doAddProjectCol(pQueryInfo, startPos + j, j, pIndex->tableIndex);
strncpy(pExpr->aliasName, pSchema[j].name, tListLen(pExpr->aliasName)); tstrncpy(pExpr->aliasName, pSchema[j].name, sizeof(pExpr->aliasName));
pIndex->columnIndex = j; pIndex->columnIndex = j;
SColumnList ids = {0}; SColumnList ids = {0};
...@@ -1453,7 +1453,7 @@ static int32_t setExprInfoForFunctions(SQueryInfo* pQueryInfo, SSchema* pSchema, ...@@ -1453,7 +1453,7 @@ static int32_t setExprInfoForFunctions(SQueryInfo* pQueryInfo, SSchema* pSchema,
} }
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, pColIndex, type, bytes, bytes, false); SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, pColIndex, type, bytes, bytes, false);
strncpy(pExpr->aliasName, columnName, tListLen(pExpr->aliasName)); tstrncpy(pExpr->aliasName, columnName, sizeof(pExpr->aliasName));
// for all queries, the timestamp column needs to be loaded // for all queries, the timestamp column needs to be loaded
SColumnIndex index = {.tableIndex = pColIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX}; SColumnIndex index = {.tableIndex = pColIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
......
...@@ -866,7 +866,7 @@ int32_t tscBuildCreateDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) { ...@@ -866,7 +866,7 @@ int32_t tscBuildCreateDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
assert(pCmd->numOfClause == 1); assert(pCmd->numOfClause == 1);
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0); STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
strncpy(pCreateDbMsg->db, pTableMetaInfo->name, tListLen(pCreateDbMsg->db)); tstrncpy(pCreateDbMsg->db, pTableMetaInfo->name, sizeof(pCreateDbMsg->db));
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
...@@ -2153,8 +2153,8 @@ int tscProcessConnectRsp(SSqlObj *pSql) { ...@@ -2153,8 +2153,8 @@ int tscProcessConnectRsp(SSqlObj *pSql) {
strcpy(pObj->acctId, pConnect->acctId); // copy acctId from response strcpy(pObj->acctId, pConnect->acctId); // copy acctId from response
int32_t len = sprintf(temp, "%s%s%s", pObj->acctId, TS_PATH_DELIMITER, pObj->db); int32_t len = sprintf(temp, "%s%s%s", pObj->acctId, TS_PATH_DELIMITER, pObj->db);
assert(len <= tListLen(pObj->db)); assert(len <= sizeof(pObj->db));
strncpy(pObj->db, temp, tListLen(pObj->db)); tstrncpy(pObj->db, temp, sizeof(pObj->db));
if (pConnect->ipList.numOfIps > 0) if (pConnect->ipList.numOfIps > 0)
tscSetMgmtIpList(&pConnect->ipList); tscSetMgmtIpList(&pConnect->ipList);
...@@ -2338,7 +2338,7 @@ static int32_t getTableMetaFromMgmt(SSqlObj *pSql, STableMetaInfo *pTableMetaInf ...@@ -2338,7 +2338,7 @@ static int32_t getTableMetaFromMgmt(SSqlObj *pSql, STableMetaInfo *pTableMetaInf
STableMetaInfo *pNewMeterMetaInfo = tscAddEmptyMetaInfo(pNewQueryInfo); STableMetaInfo *pNewMeterMetaInfo = tscAddEmptyMetaInfo(pNewQueryInfo);
assert(pNew->cmd.numOfClause == 1 && pNewQueryInfo->numOfTables == 1); assert(pNew->cmd.numOfClause == 1 && pNewQueryInfo->numOfTables == 1);
strncpy(pNewMeterMetaInfo->name, pTableMetaInfo->name, tListLen(pNewMeterMetaInfo->name)); tstrncpy(pNewMeterMetaInfo->name, pTableMetaInfo->name, sizeof(pNewMeterMetaInfo->name));
memcpy(pNew->cmd.payload, pSql->cmd.payload, pSql->cmd.payloadLen); // tag information if table does not exists. memcpy(pNew->cmd.payload, pSql->cmd.payload, pSql->cmd.payloadLen); // tag information if table does not exists.
pNew->cmd.payloadLen = pSql->cmd.payloadLen; pNew->cmd.payloadLen = pSql->cmd.payloadLen;
tscTrace("%p new pSqlObj:%p to get tableMeta, auto create:%d", pSql, pNew, pNew->cmd.autoCreated); tscTrace("%p new pSqlObj:%p to get tableMeta, auto create:%d", pSql, pNew, pNew->cmd.autoCreated);
......
...@@ -86,7 +86,7 @@ SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con ...@@ -86,7 +86,7 @@ SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con
pObj->signature = pObj; pObj->signature = pObj;
strncpy(pObj->user, user, TSDB_USER_LEN); tstrncpy(pObj->user, user, sizeof(pObj->user));
taosEncryptPass((uint8_t *)pass, strlen(pass), pObj->pass); taosEncryptPass((uint8_t *)pass, strlen(pass), pObj->pass);
if (db) { if (db) {
......
...@@ -180,7 +180,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { ...@@ -180,7 +180,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) {
assert(cfg != NULL); assert(cfg != NULL);
if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_OPTION) { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_OPTION) {
strncpy(configDir, pStr, TSDB_FILENAME_LEN); tstrncpy(configDir, pStr, TSDB_FILENAME_LEN);
cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION; cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION;
tscPrint("set config file directory:%s", pStr); tscPrint("set config file directory:%s", pStr);
} else { } else {
...@@ -234,7 +234,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { ...@@ -234,7 +234,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) {
tscPrint("failed to set locale:%s, current locale:%s", pStr, tsLocale); tscPrint("failed to set locale:%s, current locale:%s", pStr, tsLocale);
} }
strncpy(tsLocale, locale, tListLen(tsLocale)); tstrncpy(tsLocale, locale, sizeof(tsLocale));
char *charset = strrchr(tsLocale, sep); char *charset = strrchr(tsLocale, sep);
if (charset != NULL) { if (charset != NULL) {
...@@ -249,7 +249,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { ...@@ -249,7 +249,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) {
tscPrint("charset changed from %s to %s", tsCharset, charset); tscPrint("charset changed from %s to %s", tsCharset, charset);
} }
strncpy(tsCharset, charset, tListLen(tsCharset)); tstrncpy(tsCharset, charset, sizeof(tsCharset));
cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION; cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION;
} else { } else {
...@@ -286,7 +286,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { ...@@ -286,7 +286,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) {
tscPrint("charset changed from %s to %s", tsCharset, pStr); tscPrint("charset changed from %s to %s", tsCharset, pStr);
} }
strncpy(tsCharset, pStr, tListLen(tsCharset)); tstrncpy(tsCharset, pStr, sizeof(tsCharset));
cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION; cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION;
} else { } else {
tscPrint("charset:%s not valid", pStr); tscPrint("charset:%s not valid", pStr);
...@@ -324,7 +324,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { ...@@ -324,7 +324,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) {
// return -1; // return -1;
// } // }
strncpy(tsSocketType, pStr, tListLen(tsSocketType)); tstrncpy(tsSocketType, pStr, sizeof(tsSocketType));
cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION; cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION;
tscPrint("socket type is set:%s", tsSocketType); tscPrint("socket type is set:%s", tsSocketType);
} }
......
...@@ -189,7 +189,7 @@ void taosGetSystemLocale() { ...@@ -189,7 +189,7 @@ void taosGetSystemLocale() {
if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
char *locale = setlocale(LC_CTYPE, "chs"); char *locale = setlocale(LC_CTYPE, "chs");
if (locale != NULL) { if (locale != NULL) {
strncpy(tsLocale, locale, sizeof(tsLocale) / sizeof(tsLocale[0])); tstrncpy(tsLocale, locale, sizeof(tsLocale));
cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT;
uPrint("locale not configured, set to default:%s", tsLocale); uPrint("locale not configured, set to default:%s", tsLocale);
} }
......
...@@ -229,7 +229,7 @@ static void taosGetSystemLocale() { // get and set default locale ...@@ -229,7 +229,7 @@ static void taosGetSystemLocale() { // get and set default locale
uError("can't get locale from system, set it to en_US.UTF-8"); uError("can't get locale from system, set it to en_US.UTF-8");
strcpy(tsLocale, "en_US.UTF-8"); strcpy(tsLocale, "en_US.UTF-8");
} else { } else {
tstrncpy(tsLocale, locale, tListLen(tsLocale)); tstrncpy(tsLocale, locale, sizeof(tsLocale));
uError("locale not configured, set to system default:%s", tsLocale); uError("locale not configured, set to system default:%s", tsLocale);
} }
} }
...@@ -242,7 +242,7 @@ static void taosGetSystemLocale() { // get and set default locale ...@@ -242,7 +242,7 @@ static void taosGetSystemLocale() { // get and set default locale
str++; str++;
char *revisedCharset = taosCharsetReplace(str); char *revisedCharset = taosCharsetReplace(str);
strncpy(tsCharset, revisedCharset, tListLen(tsCharset)); tstrncpy(tsCharset, revisedCharset, sizeof(tsCharset));
free(revisedCharset); free(revisedCharset);
uWarn("charset not configured, set to system default:%s", tsCharset); uWarn("charset not configured, set to system default:%s", tsCharset);
......
...@@ -226,7 +226,7 @@ void taosGetSystemLocale() { ...@@ -226,7 +226,7 @@ void taosGetSystemLocale() {
if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
char *locale = setlocale(LC_CTYPE, "chs"); char *locale = setlocale(LC_CTYPE, "chs");
if (locale != NULL) { if (locale != NULL) {
strncpy(tsLocale, locale, sizeof(tsLocale) / sizeof(tsLocale[0])); tstrncpy(tsLocale, locale, sizeof(tsLocale));
cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT;
uPrint("locale not configured, set to default:%s", tsLocale); uPrint("locale not configured, set to default:%s", tsLocale);
} }
......
...@@ -6038,7 +6038,6 @@ static void buildTagQueryResult(SQInfo* pQInfo) { ...@@ -6038,7 +6038,6 @@ static void buildTagQueryResult(SQInfo* pQInfo) {
for(int32_t j = 0; j < pQuery->numOfOutput; ++j) { for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
char* data = tsdbGetTableName(pQInfo->tsdb, &item->id); char* data = tsdbGetTableName(pQInfo->tsdb, &item->id);
char* dst = pQuery->sdata[j]->data + count * ((TSDB_TABLE_NAME_LEN - 1) + VARSTR_HEADER_SIZE); char* dst = pQuery->sdata[j]->data + count * ((TSDB_TABLE_NAME_LEN - 1) + VARSTR_HEADER_SIZE);
memcpy(dst, data, varDataTLen(data)); memcpy(dst, data, varDataTLen(data));
} else {// todo refactor } else {// todo refactor
......
...@@ -51,7 +51,7 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) { ...@@ -51,7 +51,7 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) {
return NULL; return NULL;
} }
strncpy(pTSBuf->path, path, PATH_MAX); tstrncpy(pTSBuf->path, path, sizeof(pTSBuf->path));
pTSBuf->f = fopen(pTSBuf->path, "r+"); pTSBuf->f = fopen(pTSBuf->path, "r+");
if (pTSBuf->f == NULL) { if (pTSBuf->f == NULL) {
......
...@@ -458,7 +458,7 @@ int rpcGetConnInfo(void *thandle, SRpcConnInfo *pInfo) { ...@@ -458,7 +458,7 @@ int rpcGetConnInfo(void *thandle, SRpcConnInfo *pInfo) {
pInfo->clientPort = pConn->peerPort; pInfo->clientPort = pConn->peerPort;
// pInfo->serverIp = pConn->destIp; // pInfo->serverIp = pConn->destIp;
strncpy(pInfo->user, pConn->user, sizeof(pInfo->user)); tstrncpy(pInfo->user, pConn->user, sizeof(pInfo->user));
return 0; return 0;
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "os.h" #include "os.h"
#include "taosdef.h" #include "taosdef.h"
#include "tutil.h"
#include "tulog.h" #include "tulog.h"
#include "tsched.h" #include "tsched.h"
#include "ttimer.h" #include "ttimer.h"
...@@ -62,8 +63,7 @@ void *taosInitScheduler(int queueSize, int numOfThreads, const char *label) { ...@@ -62,8 +63,7 @@ void *taosInitScheduler(int queueSize, int numOfThreads, const char *label) {
} }
pSched->queueSize = queueSize; pSched->queueSize = queueSize;
strncpy(pSched->label, label, sizeof(pSched->label)); // fix buffer overflow tstrncpy(pSched->label, label, sizeof(pSched->label)); // fix buffer overflow
pSched->label[sizeof(pSched->label)-1] = '\0';
pSched->fullSlot = 0; pSched->fullSlot = 0;
pSched->emptySlot = 0; pSched->emptySlot = 0;
......
...@@ -552,8 +552,7 @@ void* taosTmrInit(int maxNumOfTmrs, int resolution, int longest, const char* lab ...@@ -552,8 +552,7 @@ void* taosTmrInit(int maxNumOfTmrs, int resolution, int longest, const char* lab
return NULL; return NULL;
} }
strncpy(ctrl->label, label, sizeof(ctrl->label)); tstrncpy(ctrl->label, label, sizeof(ctrl->label));
ctrl->label[sizeof(ctrl->label) - 1] = 0;
tmrTrace("%s timer controller is initialized, number of timer controllers: %d.", label, numOfTmrCtrl); tmrTrace("%s timer controller is initialized, number of timer controllers: %d.", label, numOfTmrCtrl);
return ctrl; return ctrl;
} }
......
...@@ -165,7 +165,7 @@ SScript *simBuildScriptObj(char *fileName) { ...@@ -165,7 +165,7 @@ SScript *simBuildScriptObj(char *fileName) {
script->type = SIM_SCRIPT_TYPE_MAIN; script->type = SIM_SCRIPT_TYPE_MAIN;
script->numOfLines = numOfLines; script->numOfLines = numOfLines;
strncpy(script->fileName, fileName, MAX_FILE_NAME_LEN); tstrncpy(script->fileName, fileName, sizeof(script->fileName));
script->optionBuffer = malloc(optionOffset); script->optionBuffer = malloc(optionOffset);
memcpy(script->optionBuffer, optionBuffer, optionOffset); memcpy(script->optionBuffer, optionBuffer, optionOffset);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册