Refactored and optimized pgsql_variable_validate_search_path

v3.0_track_search_path_param_5148
Rahim Kanji 4 months ago
parent 089524774e
commit 901fe53c6d

@ -451,47 +451,38 @@ bool pgsql_variable_validate_client_encoding(const char* value, const params_t*
bool pgsql_variable_validate_search_path(const char* value, const params_t* params, PgSQL_Session* session, char** transformed_value) {
(void)params;
(void)session;
bool result = true;
if (transformed_value) *transformed_value = nullptr;
if (value == NULL) return false;
char* copy = strdup(value);
if (copy == NULL) return false;
if (transformed_value) *transformed_value = nullptr;
if (value == nullptr) return false;
char* token = copy;
while (isspace(*token)) token++; // trim leading spaces
// NOSONAR: strlen is safe here
size_t value_len = strlen(value); // NOSONAR
if (value_len > SIZE_MAX - 1) return false;
char* end = copy + strlen(copy) - 1;
while (end > copy && isspace(*end)) *end-- = '\0'; // trim trailing spaces
char* normalized = (char*)malloc(value_len + 1);
if (normalized == nullptr) return false;
normalized[0] = '\0';
// return on back ticks
size_t norm_pos = 0;
bool first = true;
bool result = true;
char* normalized = (char*)malloc(strlen(value) * 2 + 3); // enough space
if (normalized == NULL) {
free(copy);
return false;
}
*normalized = '\0';
const char* token = value;
bool first = true;
while (*token && result) {
while (isspace(*token)) token++;
/* skip leading whitespace */
while (*token && isspace((unsigned char)*token)) token++;
if (*token == '\0') break;
char* part_start = token;
const char* part_start = token;
size_t part_len = 0;
int effective_len = 0; // for length check after de-escaping
int part_len;
char effective_len = 0; // for length check after de-escaping
if (*token == '"' || *token == '\'') {
// handle quoted identifier
char quote = *token;
token++;
char* search = token;
// quoted identifier (preserve quotes in normalized output)
char quote = *token++;
const char* search = token;
while (*search) {
if (*search == '\0') { // check for NUL
result = false;
break;
}
if (*search == quote) {
if (*(search + 1) == quote) {
search += 2;
@ -504,68 +495,66 @@ bool pgsql_variable_validate_search_path(const char* value, const params_t* para
search++;
effective_len++;
}
if (*search != quote) {
result = false;
break; // unclosed quote
}
part_len = search - part_start + 1;
part_len = (size_t)(search - part_start + 1);
token = search + 1; // skip closing quote
if (effective_len > 63) {
result = false;
break;
}
}
else {
} else {
// unquoted identifier or $user
while (*token && *token != ',' && !isspace(*token)) token++;
part_len = token - part_start;
if (part_len == 0) {
part_len = (size_t)(token - part_start);
if (part_len == 0 || part_len > 63) {
result = false;
break;
}
char part[64];
if (part_len >= 64) {
result = false;
break;
}
strncpy(part, part_start, part_len);
part[part_len] = '\0';
// validate as identifier
if (!isalpha(part[0]) && part[0] != '_') {
if (!isalpha(part_start[0]) && part_start[0] != '_') {
result = false;
break;
}
for (int i = 1; i < part_len; ++i) {
if (!isalnum(part[i]) && part[i] != '_' && part[i] != '$') {
for (size_t i = 1; i < part_len; ++i) {
if (!isalnum(part_start[i]) && part_start[i] != '_' && part_start[i] != '$') {
result = false;
break;
}
}
if (part_len > 63) {
result = false;
break;
}
if (!result) break;
}
// add to normalized
if (!first) strcat(normalized, ",");
if (!first) {
normalized[norm_pos++] = ',';
}
first = false;
strncat(normalized, part_start, part_len);
// skip comma if present
while (isspace(*token)) token++;
// append the part bytes
if (part_len > 0) {
memcpy(normalized + norm_pos, part_start, part_len);
norm_pos += part_len;
}
normalized[norm_pos] = '\0';
// skip whitespace after part
while (*token && isspace(*token)) token++;
// expect comma or end
if (*token == ',') {
token++;
} else if (*token != '\0' && !isspace(*token)) {
} else if (*token != '\0') {
// if there's more content without comma, invalid
result = false;
break;
}
}
free(copy);
if (result) {
if (transformed_value) {
*transformed_value = normalized;

Loading…
Cancel
Save