Skip to content

Commit fd9621e

Browse files
committed
Disallow map section URIs which are substrings of subsequent map section URIs
1 parent e8ac8f1 commit fd9621e

File tree

3 files changed

+67
-5
lines changed

3 files changed

+67
-5
lines changed

etc/apache2/renderd-example-map.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,5 +161,5 @@ Listen 8081
161161
# Off = a 404 is returned for that url instead.
162162
# Default: On
163163
#ModTileEnableDirtyURL Off
164-
164+
LogLevel debug
165165
</VirtualHost>

src/renderd_config.c

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,32 @@ static void process_config_string(const dictionary *ini, const char *section, co
106106
free(key);
107107
}
108108

109+
static char *process_config_string_with_trailing_slash(const dictionary *ini, const char *section, const char *name, const char **dest, const char *notfound, size_t maxlen)
110+
{
111+
char *key = name_with_section(section, name);
112+
const char *src = iniparser_getstring(ini, key, notfound);
113+
114+
g_logger(G_LOG_LEVEL_DEBUG, "\tRead %s: '%s'", key, src);
115+
116+
if (src[strnlen(src, maxlen) - 1] != '/') {
117+
char *tempsrc = strndup(src, maxlen);
118+
int len;
119+
120+
len = asprintf(&tempsrc, "%s/", src);
121+
if (len == -1) {
122+
g_logger(G_LOG_LEVEL_CRITICAL, "process_config_string_with_trailing_slash: asprintf error");
123+
exit(7);
124+
}
125+
126+
copy_string(tempsrc, dest, maxlen);
127+
free(tempsrc);
128+
} else {
129+
copy_string(src, dest, maxlen);
130+
}
131+
132+
free(key);
133+
}
134+
109135
void free_map_section(xmlconfigitem map_section)
110136
{
111137
free((void *)map_section.attribution);
@@ -239,8 +265,8 @@ void process_map_sections(const char *config_file_name, xmlconfigitem *maps_dest
239265
process_config_string(ini, section, "parameterize_style", &maps_dest[map_section_num].parameterization, "", PATH_MAX);
240266
process_config_string(ini, section, "server_alias", &maps_dest[map_section_num].server_alias, "", PATH_MAX);
241267
process_config_string(ini, section, "tiledir", &maps_dest[map_section_num].tile_dir, default_tile_dir, PATH_MAX);
242-
process_config_string(ini, section, "uri", &maps_dest[map_section_num].xmluri, "", PATH_MAX);
243268
process_config_string(ini, section, "xml", &maps_dest[map_section_num].xmlfile, "", PATH_MAX);
269+
process_config_string_with_trailing_slash(ini, section, "uri", &maps_dest[map_section_num].xmluri, "", PATH_MAX);
244270

245271
process_config_double(ini, section, "scale", &maps_dest[map_section_num].scale_factor, 1.0);
246272

@@ -275,9 +301,7 @@ void process_map_sections(const char *config_file_name, xmlconfigitem *maps_dest
275301
process_config_string(ini, section, "type", &ini_type, "png image/png png256", INILINE_MAX);
276302
ini_type_copy = strndup(ini_type, INILINE_MAX);
277303

278-
for (ini_type_part = strtok_r(ini_type_copy, " ", &ini_type_context);
279-
ini_type_part;
280-
ini_type_part = strtok_r(NULL, " ", &ini_type_context)) {
304+
for (ini_type_part = strtok_r(ini_type_copy, " ", &ini_type_context); ini_type_part; ini_type_part = strtok_r(NULL, " ", &ini_type_context)) {
281305
switch (ini_type_part_num) {
282306
case 0:
283307
copy_string(ini_type_part, &maps_dest[map_section_num].file_extension, ini_type_part_maxlen);
@@ -329,6 +353,17 @@ void process_map_sections(const char *config_file_name, xmlconfigitem *maps_dest
329353
g_logger(G_LOG_LEVEL_CRITICAL, "No map config sections were found in file: %s", config_file_name);
330354
exit(1);
331355
}
356+
357+
if (map_section_num > 0) {
358+
for (int x = 0; x < map_section_num; x++) {
359+
for (int y = x + 1; y <= map_section_num; y++) {
360+
if (strncmp(maps_dest[x].xmluri, maps_dest[y].xmluri, strnlen(maps_dest[x].xmluri, PATH_MAX)) == 0) {
361+
g_logger(G_LOG_LEVEL_CRITICAL, "Specified URI ('%s' in map section '%s') must not be a substring of any subsequent map config section's URI, e.g., '%s' in map section '%s'.", maps_dest[x].xmluri, maps_dest[x].xmlname, maps_dest[y].xmluri, maps_dest[y].xmlname);
362+
exit(7);
363+
}
364+
}
365+
}
366+
}
332367
}
333368

334369
void process_mapnik_section(const char *config_file_name, renderd_config *config_dest)

tests/renderd_config_test.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ TEST_CASE("renderd_config config parser", "specific testing")
187187

188188
for (int i = 0; i <= XMLCONFIGS_MAX; i++) {
189189
renderd_conf_file << "[map" + std::to_string(i) + "]\n";
190+
renderd_conf_file << "uri=/" + std::to_string(i) + "\n";
190191
}
191192

192193
renderd_conf_file.close();
@@ -447,4 +448,30 @@ TEST_CASE("renderd_config config parser", "specific testing")
447448
REQUIRE(WEXITSTATUS(status) == 7);
448449
REQUIRE_THAT(err_log_lines, Catch::Matchers::Contains("Duplicate renderd config section names for section 0: renderd0 & renderd"));
449450
}
451+
452+
SECTION("renderd.conf with overlapping URIs", "should return 7") {
453+
std::string map0_uri = GENERATE( "", "/map1", "/map2");
454+
455+
std::string renderd_conf = std::tmpnam(nullptr);
456+
std::ofstream renderd_conf_file;
457+
renderd_conf_file.open(renderd_conf);
458+
renderd_conf_file << "[mapnik]\n[renderd]\n";
459+
460+
renderd_conf_file << "[map0]\n";
461+
renderd_conf_file << "uri=" + map0_uri + "\n";
462+
renderd_conf_file << "[map1]\n";
463+
renderd_conf_file << "uri=/map1/1\n";
464+
renderd_conf_file << "[map2]\n";
465+
renderd_conf_file << "uri=/map2/2\n";
466+
467+
renderd_conf_file.close();
468+
469+
std::vector<std::string> argv = {"--config", renderd_conf};
470+
471+
int status = run_command(test_binary, argv);
472+
std::remove(renderd_conf.c_str());
473+
REQUIRE(WEXITSTATUS(status) == 7);
474+
REQUIRE_THAT(err_log_lines, Catch::Matchers::Contains("Specified URI ('" + map0_uri + "/' in map section 'map0') must not be a substring of any subsequent map config section's URI, e.g., '/map"));
475+
}
450476
}
477+

0 commit comments

Comments
 (0)