fix "first location" bug

reported by devel at datenbrei dot de.  The first location would
overwrite the default value for a server, triggering the "`foo' rule
specified more than once" error.  This also needed a small tweak on
how we match locations to avoid breaking other tests.
This commit is contained in:
Omar Polo 2021-02-10 16:37:08 +00:00
parent 2898780aea
commit 49b73ba1ab
3 changed files with 38 additions and 14 deletions

19
parse.y
View File

@ -44,6 +44,7 @@ int check_block_code(int);
char *check_block_fmt(char*);
int check_strip_no(int);
int check_prefork_num(int);
void advance_loc(void);
%}
@ -140,11 +141,11 @@ locations : /* empty */
| locations location
;
location : TLOCATION TSTRING '{' locopts '}' {
loc->match = $2;
if (++iloc == LOCLEN)
errx(1, "too much location rules defined");
loc++;
location : TLOCATION { advance_loc(); } TSTRING '{' locopts '}' {
/* drop the starting '/' if any */
if (*$3 == '/')
memmove($3, $3+1, strlen($3));
loc->match = $3;
}
| error '}'
;
@ -301,3 +302,11 @@ check_prefork_num(int n)
yyerror("invalid prefork number %d", n);
return n;
}
void
advance_loc(void)
{
if (++iloc == LOCLEN)
errx(1, "too much location rules defined");
loc++;
}

View File

@ -158,6 +158,11 @@ echo OK GET / with custom lang
check "should be running"
# make sure we can use different lang in different location rules
config '' 'lang "it" location "/en/*" { lang "en" } location "/de/*" { lang "de" }'
checkconf
restart
# try with CGI scripts
config '' 'cgi "*"'
checkconf
@ -204,7 +209,7 @@ echo OK GET /dir/ with custom index
check "should be running"
config '' 'location "/dir/" { default type "text/plain" index "hello" }'
config '' 'location "/dir/*" { default type "text/plain" index "hello" }'
checkconf
restart
@ -217,7 +222,7 @@ echo OK GET /dir/ with location and custom index
check "should be running"
config '' 'location "/dir/" { auto index on }'
config '' 'location "/dir/*" { auto index on }'
checkconf
restart

View File

@ -43,6 +43,8 @@ struct server_events {
int connected_clients;
static inline int matches(const char*, const char*);
static inline void reschedule_read(int, struct client*, statefn);
static inline void reschedule_write(int, struct client*, statefn);
@ -72,6 +74,14 @@ static void close_conn(int, short, void*);
static void do_accept(int, short, void*);
static void handle_sighup(int, short, void*);
static inline int
matches(const char *pattern, const char *path)
{
if (*path == '/')
path++;
return !fnmatch(pattern, path, 0);
}
static inline void
reschedule_read(int fd, struct client *c, statefn fn)
{
@ -94,7 +104,7 @@ vhost_lang(struct vhost *v, const char *path)
for (loc = &v->locations[1]; loc->match != NULL; ++loc) {
if (loc->lang != NULL) {
if (!fnmatch(loc->match, path, 0))
if (matches(loc->match, path))
return loc->lang;
}
}
@ -113,7 +123,7 @@ vhost_default_mime(struct vhost *v, const char *path)
for (loc = &v->locations[1]; loc->match != NULL; ++loc) {
if (loc->default_mime != NULL) {
if (!fnmatch(loc->match, path, 0))
if (matches(loc->match, path))
return loc->default_mime;
}
}
@ -134,7 +144,7 @@ vhost_index(struct vhost *v, const char *path)
for (loc = &v->locations[1]; loc->match != NULL; ++loc) {
if (loc->index != NULL) {
if (!fnmatch(loc->match, path, 0))
if (matches(loc->match, path))
return loc->index;
}
}
@ -154,7 +164,7 @@ vhost_auto_index(struct vhost *v, const char *path)
for (loc = &v->locations[1]; loc->match != NULL; ++loc) {
if (loc->auto_index != 0) {
if (!fnmatch(loc->match, path, 0))
if (matches(loc->match, path))
return loc->auto_index == 1;
}
}
@ -172,7 +182,7 @@ vhost_block_return(struct vhost *v, const char *path, int *code, const char **fm
for (loc = &v->locations[1]; loc->match != NULL; ++loc) {
if (loc->block_code != 0) {
if (!fnmatch(loc->match, path, 0)) {
if (matches(loc->match, path)) {
*code = loc->block_code;
*fmt = loc->block_fmt;
return 1;
@ -195,7 +205,7 @@ vhost_strip(struct vhost *v, const char *path)
for (loc = &v->locations[1]; loc->match != NULL; ++loc) {
if (loc->strip != 0) {
if (!fnmatch(loc->match, path, 0))
if (matches(loc->match, path))
return loc->strip;
}
}
@ -213,7 +223,7 @@ vhost_require_ca(struct vhost *v, const char *path)
for (loc = &v->locations[1]; loc->match != NULL; ++loc) {
if (loc->reqca != NULL) {
if (!fnmatch(loc->match, path, 0))
if (matches(loc->match, path))
return loc->reqca;
}
}