Merge commit from fork

This commit is contained in:
Andrey Volk
2026-05-07 20:18:11 +03:00
committed by GitHub
parent ce12717ad7
commit 2a7100053a
4 changed files with 335 additions and 12 deletions
+47 -12
View File
@@ -103,6 +103,10 @@ void globfree(glob_t *);
#define SWITCH_XML_WS "\t\r\n " /* whitespace */
#define SWITCH_XML_ERRL 128 /* maximum error string length */
/* Limits for entity expansion to prevent excessive resource consumption */
#define SWITCH_XML_MAX_ENTITY_EXPANSION_DEPTH 20 /* Maximum recursion depth for entity expansion */
#define SWITCH_XML_MAX_ENTITY_EXPANSION_COUNT 10000 /* Maximum number of entity expansions */
static void preprocess_exec_set(char *keyval)
{
char *key = keyval;
@@ -760,23 +764,54 @@ static switch_xml_t switch_xml_close_tag(switch_xml_root_t root, char *name, cha
return NULL;
}
/* Depth-limited version with resource limits for entity validation */
static int switch_xml_ent_ok_with_depth(char *name, char *s, char **ent, int depth, unsigned long *check_count)
{
int i;
/* Prevent excessive recursion during entity validation */
if (depth > SWITCH_XML_MAX_ENTITY_EXPANSION_DEPTH) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Entity validation depth limit exceeded (%d > %d) for entity: %s\n",
depth, SWITCH_XML_MAX_ENTITY_EXPANSION_DEPTH, name);
return 0; /* Treat as invalid - too deep */
}
for (;; s++) {
while (*s && *s != '&') {
s++; /* find next entity reference */
}
if (!*s)
return 1;
/* Increment check counter for each entity reference found */
if (++(*check_count) > SWITCH_XML_MAX_ENTITY_EXPANSION_COUNT) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Entity validation count limit exceeded (%lu > %d) for entity: %s\n",
*check_count, SWITCH_XML_MAX_ENTITY_EXPANSION_COUNT, name);
return 0; /* Treat as invalid - too many entity references */
}
if (!strncmp(s + 1, name, strlen(name)))
return 0; /* circular ref. */
for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2);
if (ent[i] && !switch_xml_ent_ok_with_depth(name, ent[i + 1], ent, depth + 1, check_count))
return 0;
}
}
/* checks for circular entity references, returns non-zero if no circular
references are found, zero otherwise */
static int switch_xml_ent_ok(char *name, char *s, char **ent)
{
int i;
unsigned long check_count = 0;
for (;; s++) {
while (*s && *s != '&')
s++; /* find next entity reference */
if (!*s)
return 1;
if (!strncmp(s + 1, name, strlen(name)))
return 0; /* circular ref. */
for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2);
if (ent[i] && !switch_xml_ent_ok(name, ent[i + 1], ent))
return 0;
}
return switch_xml_ent_ok_with_depth(name, s, ent, 0, &check_count);
}
/* called when the parser finds a processing instruction */