mirror of https://github.com/citusdata/citus.git
Replace calls to unsafe functions like memcpy and sscanf
In answer to a security audit, we double check buffer sizes and avoid known-dangerous operations such as sscanf.pull/2516/head
parent
cb119f4f73
commit
d1b182de7d
|
@ -260,15 +260,37 @@ GetConnParams(ConnectionHashKey *key, char ***keywords, char ***values,
|
|||
/* auth keywords will begin after global and runtime ones are appended */
|
||||
Index authParamsIdx = ConnParams.size + lengthof(runtimeKeywords);
|
||||
|
||||
int paramIndex = 0;
|
||||
int runtimeParamIndex = 0;
|
||||
|
||||
if (ConnParams.size + lengthof(runtimeKeywords) > ConnParams.maxSize)
|
||||
{
|
||||
/* unexpected, intended as developers rather than users */
|
||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("too many connParams entries")));
|
||||
}
|
||||
|
||||
pg_ltoa(key->port, nodePortString); /* populate node port string with port */
|
||||
|
||||
/* first step: copy global parameters to beginning of array */
|
||||
memcpy(connKeywords, ConnParams.keywords, ConnParams.size * sizeof(char *));
|
||||
memcpy(connValues, ConnParams.values, ConnParams.size * sizeof(char *));
|
||||
for (paramIndex = 0; paramIndex < ConnParams.size; paramIndex++)
|
||||
{
|
||||
/* copy the keyword&value pointers to the new array */
|
||||
connKeywords[paramIndex] = ConnParams.keywords[paramIndex];
|
||||
connValues[paramIndex] = ConnParams.values[paramIndex];
|
||||
}
|
||||
|
||||
/* second step: begin at end of global params and copy runtime ones */
|
||||
memcpy(&connKeywords[ConnParams.size], runtimeKeywords, sizeof(runtimeKeywords));
|
||||
memcpy(&connValues[ConnParams.size], runtimeValues, sizeof(runtimeValues));
|
||||
for (runtimeParamIndex = 0;
|
||||
runtimeParamIndex < lengthof(runtimeKeywords);
|
||||
runtimeParamIndex++)
|
||||
{
|
||||
/* copy the keyword&value pointers to the new array */
|
||||
connKeywords[ConnParams.size + runtimeParamIndex] =
|
||||
(char *) runtimeKeywords[runtimeParamIndex];
|
||||
connValues[ConnParams.size + runtimeParamIndex] =
|
||||
(char *) runtimeValues[runtimeParamIndex];
|
||||
}
|
||||
|
||||
/* final step: add terminal NULL, required by libpq */
|
||||
connKeywords[authParamsIdx] = connValues[authParamsIdx] = NULL;
|
||||
|
|
|
@ -689,7 +689,7 @@ FindOrCreatePlacementEntry(ShardPlacement *placement)
|
|||
ColocatedPlacementsHashKey key;
|
||||
ColocatedPlacementsHashEntry *colocatedEntry = NULL;
|
||||
|
||||
strcpy(key.nodeName, placement->nodeName);
|
||||
strlcpy(key.nodeName, placement->nodeName, MAX_NODE_LENGTH);
|
||||
key.nodePort = placement->nodePort;
|
||||
key.colocationGroupId = placement->colocationGroupId;
|
||||
key.representativeValue = placement->representativeValue;
|
||||
|
|
|
@ -692,12 +692,12 @@ void
|
|||
AppendShardIdToName(char **name, uint64 shardId)
|
||||
{
|
||||
char extendedName[NAMEDATALEN];
|
||||
uint32 extendedNameLength = 0;
|
||||
int nameLength = strlen(*name);
|
||||
char shardIdAndSeparator[NAMEDATALEN];
|
||||
int shardIdAndSeparatorLength;
|
||||
uint32 longNameHash = 0;
|
||||
int multiByteClipLength = 0;
|
||||
int neededBytes = 0;
|
||||
|
||||
if (nameLength >= NAMEDATALEN)
|
||||
{
|
||||
|
@ -756,11 +756,20 @@ AppendShardIdToName(char **name, uint64 shardId)
|
|||
SHARD_NAME_SEPARATOR, longNameHash,
|
||||
shardIdAndSeparator);
|
||||
}
|
||||
extendedNameLength = strlen(extendedName) + 1;
|
||||
Assert(extendedNameLength <= NAMEDATALEN);
|
||||
|
||||
(*name) = (char *) repalloc((*name), extendedNameLength);
|
||||
snprintf((*name), extendedNameLength, "%s", extendedName);
|
||||
(*name) = (char *) repalloc((*name), NAMEDATALEN);
|
||||
neededBytes = snprintf((*name), NAMEDATALEN, "%s", extendedName);
|
||||
if (neededBytes < 0)
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of memory: %s", strerror(errno))));
|
||||
}
|
||||
else if (neededBytes >= NAMEDATALEN)
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
||||
errmsg("new name %s would be truncated at %d characters",
|
||||
extendedName, NAMEDATALEN)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "distributed/transaction_management.h"
|
||||
#include "distributed/transaction_recovery.h"
|
||||
#include "distributed/worker_manager.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/hsearch.h"
|
||||
|
||||
|
||||
|
@ -1321,21 +1322,79 @@ Assign2PCIdentifier(MultiConnection *connection)
|
|||
* format ParsePreparedTransactionName returns false, and true otherwise.
|
||||
*/
|
||||
bool
|
||||
ParsePreparedTransactionName(char *preparedTransactionName, int *groupId, int *procId,
|
||||
uint64 *transactionNumber, uint32 *connectionNumber)
|
||||
ParsePreparedTransactionName(char *preparedTransactionName,
|
||||
int *groupId, int *procId,
|
||||
uint64 *transactionNumber,
|
||||
uint32 *connectionNumber)
|
||||
{
|
||||
const int expectedFieldCount = 4;
|
||||
int parsedFieldCount = 0;
|
||||
bool nameValid = false;
|
||||
char *currentCharPointer = preparedTransactionName;
|
||||
|
||||
parsedFieldCount = sscanf(preparedTransactionName, PREPARED_TRANSACTION_NAME_FORMAT,
|
||||
groupId, procId, transactionNumber, connectionNumber);
|
||||
if (parsedFieldCount == expectedFieldCount)
|
||||
currentCharPointer = strchr(currentCharPointer, '_');
|
||||
if (currentCharPointer == NULL)
|
||||
{
|
||||
nameValid = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return nameValid;
|
||||
/* step ahead of the current '_' character */
|
||||
++currentCharPointer;
|
||||
|
||||
*groupId = strtol(currentCharPointer, NULL, 10);
|
||||
|
||||
if ((*groupId == 0 && errno == EINVAL) ||
|
||||
(*groupId == INT_MAX && errno == ERANGE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
currentCharPointer = strchr(currentCharPointer, '_');
|
||||
if (currentCharPointer == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* step ahead of the current '_' character */
|
||||
++currentCharPointer;
|
||||
|
||||
*procId = strtol(currentCharPointer, NULL, 10);
|
||||
if ((*procId == 0 && errno == EINVAL) ||
|
||||
(*procId == INT_MAX && errno == ERANGE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
currentCharPointer = strchr(currentCharPointer, '_');
|
||||
if (currentCharPointer == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* step ahead of the current '_' character */
|
||||
++currentCharPointer;
|
||||
|
||||
*transactionNumber = pg_strtouint64(currentCharPointer, NULL, 10);
|
||||
if ((*transactionNumber == 0 && errno != 0) ||
|
||||
(*transactionNumber == ULLONG_MAX && errno == ERANGE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
currentCharPointer = strchr(currentCharPointer, '_');
|
||||
if (currentCharPointer == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* step ahead of the current '_' character */
|
||||
++currentCharPointer;
|
||||
|
||||
*connectionNumber = strtoul(currentCharPointer, NULL, 10);
|
||||
if ((*connectionNumber == 0 && errno == EINVAL) ||
|
||||
(*connectionNumber == UINT_MAX && errno == ERANGE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue