LCOV - code coverage report
Current view: top level - lib - lwan-config.c (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 350 433 80.8 %
Date: 2023-04-18 16:19:03 Functions: 56 59 94.9 %

          Line data    Source code
       1             : /*
       2             :  * lwan - web server
       3             :  * Copyright (c) 2017 L. A. F. Pereira <l@tia.mat.br>
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU General Public License
       7             :  * as published by the Free Software Foundation; either version 2
       8             :  * of the License, or any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  * GNU General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with this program; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
      18             :  */
      19             : 
      20             : #define _GNU_SOURCE
      21             : 
      22             : #include <ctype.h>
      23             : #include <errno.h>
      24             : #include <fcntl.h>
      25             : #include <stdarg.h>
      26             : #include <stdbool.h>
      27             : #include <stdio.h>
      28             : #include <stdlib.h>
      29             : #include <string.h>
      30             : #include <sys/mman.h>
      31             : #include <sys/stat.h>
      32             : #include <sys/types.h>
      33             : #include <unistd.h>
      34             : 
      35             : #include "lwan-private.h"
      36             : #include "lwan-status.h"
      37             : #include "lwan-config.h"
      38             : #include "lwan-strbuf.h"
      39             : 
      40             : #include "ringbuffer.h"
      41             : 
      42             : #define LEX_ERROR(lexer, fmt, ...)                                             \
      43             :     ({                                                                         \
      44             :         config_error(config_from_lexer(lexer), "%s" fmt,                       \
      45             :                      "Syntax error: ", ##__VA_ARGS__);                         \
      46             :         NULL;                                                                  \
      47             :     })
      48             : 
      49             : #define PARSER_ERROR(parser, fmt, ...)                                         \
      50             :     ({                                                                         \
      51             :         config_error(config_from_parser(parser), "%s" fmt,                     \
      52             :                      "Parsing error: ", ##__VA_ARGS__);                        \
      53             :         NULL;                                                                  \
      54             :     })
      55             : 
      56             : #define INTERNAL_ERROR(parser, fmt, ...)                                       \
      57             :     ({                                                                         \
      58             :         config_error(config_from_parser(parser), "%s" fmt,                     \
      59             :                      "Internal error: ", ##__VA_ARGS__);                       \
      60             :         NULL;                                                                  \
      61             :     })
      62             : 
      63             : #define FOR_EACH_LEXEME(X)                                                      \
      64             :     X(STRING) X(EQUAL) X(OPEN_BRACKET) X(CLOSE_BRACKET) X(LINEFEED) X(VARIABLE) \
      65             :     X(VARIABLE_DEFAULT) X(EOF)
      66             : 
      67             : #define GENERATE_ENUM(id) LEXEME_ ## id,
      68             : 
      69             : enum lexeme_type {
      70             :     FOR_EACH_LEXEME(GENERATE_ENUM)
      71             :     TOTAL_LEXEMES
      72             : };
      73             : 
      74             : #undef GENERATE_ENUM
      75             : 
      76             : struct lexeme {
      77             :     enum lexeme_type type;
      78             :     struct {
      79             :         const char *value;
      80             :         size_t len;
      81             :     } value;
      82             : };
      83             : 
      84     1054704 : DEFINE_RING_BUFFER_TYPE(lexeme_ring_buffer, struct lexeme, 4)
      85      315038 : DEFINE_RING_BUFFER_TYPE(config_ring_buffer, struct config_line, 4)
      86             : 
      87             : struct lexer {
      88             :     void *(*state)(struct lexer *);
      89             :     const char *start, *pos, *end;
      90             :     struct lexeme_ring_buffer buffer;
      91             :     int cur_line;
      92             : };
      93             : 
      94             : struct parser {
      95             :     void *(*state)(struct parser *);
      96             :     struct lexer lexer;
      97             :     struct lexeme_ring_buffer buffer;
      98             :     struct config_ring_buffer items;
      99             :     struct lwan_strbuf strbuf;
     100             : };
     101             : 
     102             : struct config {
     103             :     struct parser parser;
     104             :     char *error_message;
     105             :     struct {
     106             :         void *addr;
     107             :         size_t sz;
     108             :     } mapped;
     109             :     int opened_brackets;
     110             : };
     111             : 
     112         440 : unsigned int parse_time_period(const char *str, unsigned int default_value)
     113             : {
     114         440 :     unsigned int total = 0;
     115             :     unsigned int period;
     116         440 :     int ignored_spaces = 0;
     117             :     char multiplier;
     118             : 
     119         440 :     if (!str)
     120          87 :         return default_value;
     121             : 
     122       89707 :     while (*str) {
     123             :         /* This check is necessary to avoid making sscanf() take an incredible
     124             :          * amount of time while trying to scan the input for a number.  Fix for
     125             :          * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=44910 */
     126       89528 :         if (isspace(*str)) {
     127       89175 :             ignored_spaces++;
     128             : 
     129       89175 :             if (ignored_spaces > 1024)
     130          87 :                 break;
     131             : 
     132       89088 :             continue;
     133             :         }
     134             : 
     135         353 :         if (sscanf(str, "%u%c", &period, &multiplier) != 2)
     136          87 :             break;
     137             : 
     138         266 :         switch (multiplier) {
     139         174 :         case 's': total += period; break;
     140           0 :         case 'm': total += period * ONE_MINUTE; break;
     141           5 :         case 'h': total += period * ONE_HOUR; break;
     142           0 :         case 'd': total += period * ONE_DAY; break;
     143           0 :         case 'w': total += period * ONE_WEEK; break;
     144          87 :         case 'M': total += period * ONE_MONTH; break;
     145           0 :         case 'y': total += period * ONE_YEAR; break;
     146           0 :         default:
     147           0 :             lwan_status_warning("Ignoring unknown multiplier: %c",
     148             :                         multiplier);
     149             :         }
     150             : 
     151         266 :         str = strchr(str, multiplier) + 1;
     152             :     }
     153             : 
     154         353 :     return total ? total : default_value;
     155             : }
     156             : 
     157         628 : long long parse_long_long(const char *value, long long default_value)
     158             : {
     159             :     char *endptr;
     160             :     long long parsed;
     161             : 
     162         628 :     if (!value)
     163          87 :         return default_value;
     164             : 
     165         541 :     errno = 0;
     166         541 :     parsed = strtoll(value, &endptr, 0);
     167             : 
     168         541 :     if (errno != 0)
     169           0 :         return default_value;
     170             : 
     171         541 :     if (*endptr != '\0' || value == endptr)
     172           0 :         return default_value;
     173             : 
     174         541 :     return parsed;
     175             : }
     176             : 
     177         621 : long parse_long(const char *value, long default_value)
     178             : {
     179         621 :     long long long_long_value = parse_long_long(value, default_value);
     180             : 
     181             :     if ((long long)(long)long_long_value != long_long_value)
     182             :         return default_value;
     183             : 
     184         621 :     return (long)long_long_value;
     185             : }
     186             : 
     187         265 : int parse_int(const char *value, int default_value)
     188             : {
     189         265 :     long long_value = parse_long(value, default_value);
     190             : 
     191         265 :     if ((long)(int)long_value != long_value)
     192           0 :         return default_value;
     193             : 
     194         265 :     return (int)long_value;
     195             : }
     196             : 
     197         696 : bool parse_bool(const char *value, bool default_value)
     198             : {
     199         696 :     if (!value)
     200         174 :         return default_value;
     201             : 
     202         522 :     if (streq(value, "true") || streq(value, "on") || streq(value, "yes"))
     203         435 :         return true;
     204             : 
     205          87 :     if (streq(value, "false") || streq(value, "off") || streq(value, "no"))
     206          87 :         return false;
     207             : 
     208           0 :     return parse_int(value, default_value);
     209             : }
     210             : 
     211           0 : bool config_error(struct config *conf, const char *fmt, ...)
     212             : {
     213             :     va_list values;
     214             :     int len;
     215             :     char *output;
     216             : 
     217           0 :     if (conf->error_message)
     218           0 :         return false;
     219             : 
     220           0 :     va_start(values, fmt);
     221           0 :     len = vasprintf(&output, fmt, values);
     222           0 :     va_end(values);
     223             : 
     224           0 :     if (len >= 0) {
     225           0 :         conf->error_message = output;
     226           0 :         return true;
     227             :     }
     228             : 
     229           0 :     conf->error_message = NULL;
     230           0 :     return false;
     231             : }
     232             : 
     233       82630 : static void emit_lexeme(struct lexer *lexer, struct lexeme *lexeme)
     234             : {
     235       82630 :     if (lexeme_ring_buffer_try_put(&lexer->buffer, lexeme))
     236       82630 :         lexer->start = lexer->pos;
     237       82630 : }
     238             : 
     239       83152 : static size_t current_len(struct lexer *lexer)
     240             : {
     241       83152 :     return (size_t)(lexer->pos - lexer->start);
     242             : }
     243             : 
     244       82630 : static void emit(struct lexer *lexer, enum lexeme_type type)
     245             : {
     246      165260 :     struct lexeme lexeme = {
     247             :         .type = type,
     248       82630 :         .value = {.value = lexer->start, .len = current_len(lexer)},
     249             :     };
     250       82630 :     emit_lexeme(lexer, &lexeme);
     251       82630 : }
     252             : 
     253      832990 : static int next(struct lexer *lexer)
     254             : {
     255      832990 :     if (lexer->pos >= lexer->end) {
     256         356 :         lexer->pos = lexer->end + 1;
     257         356 :         return '\0';
     258             :     }
     259             : 
     260      832634 :     int r = *lexer->pos;
     261      832634 :     lexer->pos++;
     262             : 
     263      832634 :     if (r == '\n')
     264       34155 :         lexer->cur_line++;
     265             : 
     266      832634 :     return r;
     267             : }
     268             : 
     269      224537 : static void ignore(struct lexer *lexer)
     270             : {
     271      224537 :     lexer->start = lexer->pos;
     272      224537 : }
     273             : 
     274        2446 : static void advance_n(struct lexer *lexer, size_t n)
     275             : {
     276        2446 :     lexer->pos += n;
     277        2446 :     ignore(lexer);
     278        2446 : }
     279             : 
     280       36046 : static void backup(struct lexer *lexer)
     281             : {
     282       36046 :     lexer->pos--;
     283             : 
     284       36046 :     if (*lexer->pos == '\n')
     285        8177 :         lexer->cur_line--;
     286       36046 : }
     287             : 
     288        1663 : static int peek(struct lexer *lexer)
     289             : {
     290        1663 :     int chr = next(lexer);
     291             : 
     292        1663 :     backup(lexer);
     293             : 
     294        1663 :     return chr;
     295             : }
     296             : 
     297      202796 : static size_t remaining(struct lexer *lexer)
     298             : {
     299      202796 :     return (size_t)(lexer->end - lexer->pos);
     300             : }
     301             : 
     302             : static void *lex_config(struct lexer *lexer);
     303             : static void *lex_variable(struct lexer *lexer);
     304             : 
     305      275156 : static bool is_string(int chr)
     306             : {
     307      275156 :     return chr && !isspace(chr) && chr != '=' && chr != '#' && chr != '{' && chr != '}';
     308             : }
     309             : 
     310       32019 : static void *lex_string(struct lexer *lexer)
     311             : {
     312             :     int chr;
     313             : 
     314             :     do {
     315      243137 :         chr = next(lexer);
     316             : 
     317      243137 :         if (chr == '$' && peek(lexer) == '{') {
     318           0 :             backup(lexer);
     319           0 :             emit(lexer, LEXEME_STRING);
     320             : 
     321           0 :             advance_n(lexer, strlen("{"));
     322             : 
     323           0 :             return lex_variable;
     324             :         }
     325      243137 :     } while (is_string(chr));
     326             : 
     327       32019 :     backup(lexer);
     328       32019 :     emit(lexer, LEXEME_STRING);
     329             : 
     330       32019 :     return lex_config;
     331             : }
     332             : 
     333       10995 : static struct config *config_from_parser(struct parser *parser)
     334             : {
     335       10995 :     return container_of(parser, struct config, parser);
     336             : }
     337             : 
     338           0 : static struct config *config_from_lexer(struct lexer *lexer)
     339             : {
     340           0 :     struct parser *parser = container_of(lexer, struct parser, lexer);
     341             : 
     342           0 :     return config_from_parser(parser);
     343             : }
     344             : 
     345      202796 : static bool lex_streq(struct lexer *lexer, const char *str, size_t s)
     346             : {
     347      202796 :     if (remaining(lexer) < s)
     348           0 :         return false;
     349             : 
     350      202796 :     return !strncmp(lexer->pos, str, s);
     351             : }
     352             : 
     353        1141 : static void *lex_multiline_string(struct lexer *lexer)
     354             : {
     355        1141 :     const char *end = (peek(lexer) == '"') ? "\"\"\"" : "'''";
     356             : 
     357        1141 :     advance_n(lexer, strlen("'''") - 1);
     358             : 
     359             :     do {
     360      201655 :         if (lex_streq(lexer, end, 3)) {
     361        1141 :             emit(lexer, LEXEME_STRING);
     362        1141 :             lexer->pos += 3;
     363             : 
     364        1141 :             return lex_config;
     365             :         }
     366      200514 :     } while (next(lexer) != '\0');
     367             : 
     368           0 :     return LEX_ERROR(lexer, "EOF while scanning multiline string");
     369             : }
     370             : 
     371        4176 : static bool is_variable(int chr)
     372             : {
     373        4176 :     return isalpha(chr) || chr == '_';
     374             : }
     375             : 
     376         261 : static void *lex_variable_default(struct lexer *lexer)
     377             : {
     378             :     int chr;
     379             : 
     380             :     do {
     381         609 :         chr = next(lexer);
     382             : 
     383         609 :         if (chr == '}') {
     384         261 :             backup(lexer);
     385         261 :             emit(lexer, LEXEME_STRING);
     386             : 
     387         261 :             advance_n(lexer, strlen("}"));
     388             : 
     389         261 :             return lex_config;
     390             :         }
     391         348 :     } while (chr != '\0');
     392             : 
     393           0 :     return LEX_ERROR(lexer, "EOF while scanning for default value for variable");
     394             : }
     395             : 
     396         522 : static void *lex_variable(struct lexer *lexer)
     397             : {
     398             :     int chr;
     399             : 
     400         522 :     advance_n(lexer, strlen("${") - 1);
     401             : 
     402             :     do {
     403        4698 :         chr = next(lexer);
     404             : 
     405        4698 :         if (chr == ':') {
     406         261 :             backup(lexer);
     407             : 
     408         261 :             if (!current_len(lexer))
     409           0 :                 return LEX_ERROR(lexer, "Expecting environment variable name");
     410             : 
     411         261 :             emit(lexer, LEXEME_VARIABLE_DEFAULT);
     412         261 :             advance_n(lexer, strlen(":"));
     413         261 :             return lex_variable_default;
     414             :         }
     415             : 
     416        4437 :         if (chr == '}') {
     417         261 :             backup(lexer);
     418             : 
     419         261 :             if (!current_len(lexer))
     420           0 :                 return LEX_ERROR(lexer, "Expecting environment variable name");
     421             : 
     422         261 :             emit(lexer, LEXEME_VARIABLE);
     423         261 :             advance_n(lexer, strlen("}"));
     424             : 
     425         261 :             return lex_config;
     426             :         }
     427        4176 :     } while (is_variable(chr));
     428             : 
     429           0 :     return LEX_ERROR(lexer, "EOF while scanning for end of variable");
     430             : }
     431             : 
     432       82615 : static bool is_comment(int chr)
     433             : {
     434       82615 :     return chr != '\0' && chr != '\n';
     435             : }
     436             : 
     437        1581 : static void *lex_comment(struct lexer *lexer)
     438             : {
     439       82615 :     while (is_comment(next(lexer)))
     440             :         ;
     441        1581 :     backup(lexer);
     442        1581 :     return lex_config;
     443             : }
     444             : 
     445       77663 : static void *lex_config(struct lexer *lexer)
     446             : {
     447      222091 :     while (true) {
     448      299754 :         int chr = next(lexer);
     449             : 
     450      299754 :         if (chr == '\0')
     451         356 :             break;
     452             : 
     453      299398 :         if (chr == '\n') {
     454       21625 :             emit(lexer, LEXEME_LINEFEED);
     455       21625 :             return lex_config;
     456             :         }
     457             : 
     458      277773 :         if (isspace(chr)) {
     459      222091 :             ignore(lexer);
     460      222091 :             continue;
     461             :         }
     462             : 
     463       55682 :         if (chr == '{') {
     464        4708 :             emit(lexer, LEXEME_OPEN_BRACKET);
     465        4708 :             return lex_config;
     466             :         }
     467             : 
     468       50974 :         if (chr == '}') {
     469             :             /* Emitting a linefeed lexeme before a close bracket lexeme
     470             :              * simplifies the parser and allows for situations where a
     471             :              * section is closed when declaring a key/value pair
     472             :              * (e.g. "section{key=value}" all in a single line).
     473             :              */
     474        5931 :             emit(lexer, LEXEME_LINEFEED);
     475        5931 :             emit(lexer, LEXEME_CLOSE_BRACKET);
     476        5931 :             return lex_config;
     477             :         }
     478             : 
     479       45043 :         if (chr == '=') {
     480        9780 :             emit(lexer, LEXEME_EQUAL);
     481        9780 :             return lex_config;
     482             :         }
     483             : 
     484       35263 :         if (chr == '#')
     485        1581 :             return lex_comment;
     486             : 
     487       33682 :         if (chr == '\'' && lex_streq(lexer, "''", 2))
     488         880 :             return lex_multiline_string;
     489       32802 :         if (chr == '"' && lex_streq(lexer, "\"\"", 2))
     490         261 :             return lex_multiline_string;
     491             : 
     492       32541 :         if (chr == '$' && peek(lexer) == '{')
     493         522 :             return lex_variable;
     494             : 
     495       32019 :         if (is_string(chr))
     496       32019 :             return lex_string;
     497             : 
     498           0 :         return LEX_ERROR(lexer, "Invalid character: '%c'", chr);
     499             :     }
     500             : 
     501         356 :     emit(lexer, LEXEME_LINEFEED);
     502         356 :     emit(lexer, LEXEME_EOF);
     503             : 
     504         356 :     return NULL;
     505             : }
     506             : 
     507       82630 : static const struct lexeme *lex_next(struct lexer *lexer)
     508             : {
     509      195817 :     while (lexer->state) {
     510             :         const struct lexeme *lexeme;
     511             : 
     512      195105 :         if ((lexeme = lexeme_ring_buffer_get_ptr_or_null(&lexer->buffer)))
     513       81918 :             return lexeme;
     514             : 
     515      113187 :         lexer->state = lexer->state(lexer);
     516             :     }
     517             : 
     518         712 :     return lexeme_ring_buffer_get_ptr_or_null(&lexer->buffer);
     519             : }
     520             : 
     521             : static void *parse_config(struct parser *parser);
     522             : static void *parse_section_end(struct parser *parser);
     523             : 
     524             : #define ENV_VAR_NAME_LEN_MAX 64
     525             : 
     526             : static __attribute__((noinline)) const char *
     527         522 : secure_getenv_len(struct parser *parser, const char *key, size_t len)
     528             : {
     529         522 :     if (UNLIKELY(len > ENV_VAR_NAME_LEN_MAX)) {
     530           0 :         return PARSER_ERROR(parser, "Variable name \"%.*s\" exceeds %d bytes",
     531             :                             (int)len, key, ENV_VAR_NAME_LEN_MAX);
     532             :     }
     533             : 
     534         522 :     return secure_getenv(strndupa(key, len));
     535             : }
     536             : 
     537        7953 : static void *parse_key_value(struct parser *parser)
     538             : {
     539        7953 :     struct config_line line = {.type = CONFIG_LINE_TYPE_LINE};
     540             :     const struct lexeme *lexeme;
     541        7953 :     enum lexeme_type last_lexeme = TOTAL_LEXEMES;
     542             :     size_t key_size;
     543             : 
     544       28045 :     while ((lexeme = lexeme_ring_buffer_get_ptr_or_null(&parser->buffer))) {
     545       12139 :         if (lexeme->type != LEXEME_STRING)
     546           0 :             return PARSER_ERROR(parser, "Expecting string");
     547             : 
     548       12139 :         lwan_strbuf_append_str(&parser->strbuf, lexeme->value.value,
     549       12139 :                                lexeme->value.len);
     550             : 
     551       12139 :         if (!lexeme_ring_buffer_empty(&parser->buffer))
     552        4186 :             lwan_strbuf_append_char(&parser->strbuf, '_');
     553             :     }
     554        7953 :     key_size = lwan_strbuf_get_length(&parser->strbuf);
     555        7953 :     lwan_strbuf_append_char(&parser->strbuf, '\0');
     556             : 
     557       19821 :     while ((lexeme = lex_next(&parser->lexer))) {
     558       19821 :         switch (lexeme->type) {
     559         261 :         case LEXEME_VARIABLE: {
     560         261 :             const char *value = secure_getenv_len(parser, lexeme->value.value,
     561         261 :                                                   lexeme->value.len);
     562         261 :             if (!value) {
     563           0 :                 return PARSER_ERROR(
     564             :                     parser, "Variable '$%.*s' not defined in environment",
     565             :                     (int)lexeme->value.len, lexeme->value.value);
     566             :             }
     567             : 
     568         261 :             lwan_strbuf_append_strz(&parser->strbuf, value);
     569             : 
     570         261 :             break;
     571             :         }
     572             : 
     573         261 :         case LEXEME_VARIABLE_DEFAULT: {
     574         261 :             const char *value = secure_getenv_len(parser, lexeme->value.value,
     575         261 :                                                   lexeme->value.len);
     576         261 :             const struct lexeme *var_name = lexeme;
     577             : 
     578         261 :             if (!(lexeme = lex_next(&parser->lexer))) {
     579           0 :                 return PARSER_ERROR(
     580             :                     parser, "Default value for variable '$%.*s' not given",
     581             :                     (int)var_name->value.len, var_name->value.value);
     582             :             }
     583             : 
     584         261 :             if (lexeme->type != LEXEME_STRING)
     585           0 :                 return PARSER_ERROR(parser, "Wrong format for default value");
     586             : 
     587         261 :             if (!value) {
     588         234 :                 lwan_status_debug(
     589             :                     "Using default value of '%.*s' for variable '${%.*s}'",
     590             :                     (int)lexeme->value.len, lexeme->value.value,
     591             :                     (int)var_name->value.len, var_name->value.value);
     592         234 :                 lwan_strbuf_append_str(&parser->strbuf, lexeme->value.value,
     593         234 :                                        lexeme->value.len);
     594             :             } else {
     595          27 :                 lwan_strbuf_append_strz(&parser->strbuf, value);
     596             :             }
     597             : 
     598         261 :             break;
     599             :         }
     600             : 
     601        1827 :         case LEXEME_EQUAL:
     602        1827 :             lwan_strbuf_append_char(&parser->strbuf, '=');
     603        1827 :             break;
     604             : 
     605        9519 :         case LEXEME_STRING:
     606        9519 :             if (last_lexeme == LEXEME_STRING)
     607         261 :                 lwan_strbuf_append_char(&parser->strbuf, ' ');
     608             : 
     609        9519 :             lwan_strbuf_append_str(&parser->strbuf, lexeme->value.value,
     610        9519 :                                    lexeme->value.len);
     611             : 
     612        9519 :             break;
     613             : 
     614        7953 :         case LEXEME_LINEFEED:
     615        7953 :             line.key = lwan_strbuf_get_buffer(&parser->strbuf);
     616        7953 :             line.value = line.key + key_size + 1;
     617             : 
     618        7953 :             if (config_ring_buffer_try_put(&parser->items, &line))
     619        7953 :                 return parse_config;
     620             : 
     621           0 :             return PARSER_ERROR(parser,
     622             :                                 "Could not add key/value to ring buffer");
     623             : 
     624           0 :         case LEXEME_OPEN_BRACKET:
     625           0 :             return PARSER_ERROR(parser, "Open bracket not expected here");
     626             : 
     627           0 :         case LEXEME_CLOSE_BRACKET:
     628           0 :             return INTERNAL_ERROR(
     629             :                 parser, "Close bracket found while parsing key/value");
     630             : 
     631           0 :         case LEXEME_EOF:
     632           0 :             return INTERNAL_ERROR(
     633             :                 parser, "EOF found while parsing key/value");
     634             : 
     635             :         case TOTAL_LEXEMES:
     636             :             __builtin_unreachable();
     637             :         }
     638             : 
     639       11868 :         last_lexeme = lexeme->type;
     640             :     }
     641             : 
     642           0 :     return PARSER_ERROR(parser, "EOF while parsing key-value");
     643             : }
     644             : 
     645        5884 : static void *parse_section(struct parser *parser)
     646             : {
     647             :     const struct lexeme *lexeme;
     648             :     size_t name_len;
     649             : 
     650        5884 :     lexeme = lexeme_ring_buffer_get_ptr_or_null(&parser->buffer);
     651        5884 :     if (!lexeme || lexeme->type != LEXEME_STRING)
     652           0 :         return PARSER_ERROR(parser, "Expecting a string");
     653             : 
     654        5884 :     lwan_strbuf_append_str(&parser->strbuf, lexeme->value.value,
     655        5884 :                            lexeme->value.len);
     656        5884 :     name_len = lexeme->value.len;
     657        5884 :     lwan_strbuf_append_char(&parser->strbuf, '\0');
     658             : 
     659       17386 :     while ((lexeme = lexeme_ring_buffer_get_ptr_or_null(&parser->buffer))) {
     660        5618 :         if (lexeme->type != LEXEME_STRING)
     661           0 :             return PARSER_ERROR(parser, "Expecting a string");
     662             : 
     663        5618 :         lwan_strbuf_append_str(&parser->strbuf, lexeme->value.value,
     664        5618 :                                lexeme->value.len);
     665             : 
     666        5618 :         if (!lexeme_ring_buffer_empty(&parser->buffer))
     667           0 :             lwan_strbuf_append_char(&parser->strbuf, ' ');
     668             :     }
     669             : 
     670       11768 :     struct config_line line = {
     671             :         .type = CONFIG_LINE_TYPE_SECTION,
     672        5884 :         .key = lwan_strbuf_get_buffer(&parser->strbuf),
     673        5884 :         .value = lwan_strbuf_get_buffer(&parser->strbuf) + name_len + 1,
     674             :     };
     675        5884 :     return config_ring_buffer_try_put(&parser->items, &line) ? parse_config
     676        5884 :                                                              : NULL;
     677             : }
     678             : 
     679        1176 : static void *parse_section_shorthand(struct parser *parser)
     680             : {
     681        1176 :     void *next_state = parse_section(parser);
     682             : 
     683        1176 :     if (next_state) {
     684        1176 :         struct config_line line = {.type = CONFIG_LINE_TYPE_SECTION_END};
     685             : 
     686        1176 :         if (config_ring_buffer_try_put(&parser->items, &line))
     687        1176 :             return next_state;
     688             : 
     689           0 :         return INTERNAL_ERROR(parser, "couldn't append line to internal ring buffer");
     690             :     }
     691             : 
     692           0 :     return NULL;
     693             : }
     694             : 
     695        5931 : static void *parse_section_end(struct parser *parser)
     696             : {
     697        5931 :     struct config_line line = {.type = CONFIG_LINE_TYPE_SECTION_END};
     698        5931 :     struct config *config = config_from_parser(parser);
     699             : 
     700        5931 :     if (!config->opened_brackets)
     701           0 :         return PARSER_ERROR(parser, "Section closed before it opened");
     702             : 
     703        5931 :     if (!lexeme_ring_buffer_empty(&parser->buffer))
     704           0 :         return PARSER_ERROR(parser, "Not expecting a close bracket here");
     705             : 
     706        5931 :     if (!config_ring_buffer_try_put(&parser->items, &line)) {
     707           0 :         return INTERNAL_ERROR(parser,
     708             :                               "could not store section end in ring buffer");
     709             :     }
     710             : 
     711        5931 :     config->opened_brackets--;
     712             : 
     713        5931 :     return parse_config;
     714             : }
     715             : 
     716       62548 : static void *parse_config(struct parser *parser)
     717             : {
     718       62548 :     const struct lexeme *lexeme = lex_next(&parser->lexer);
     719             : 
     720       62548 :     if (!lexeme) {
     721             :         /* EOF is signaled by a LEXEME_EOF from the parser, so
     722             :          * this should never happen. */
     723           0 :         return INTERNAL_ERROR(parser, "could not obtain lexeme");
     724             :     }
     725             : 
     726       62548 :     switch (lexeme->type) {
     727        7953 :     case LEXEME_EQUAL:
     728        7953 :         if (lexeme_ring_buffer_empty(&parser->buffer))
     729           0 :             return PARSER_ERROR(parser, "Keys can´t be empty");
     730             : 
     731        7953 :         return parse_key_value;
     732             : 
     733        4708 :     case LEXEME_OPEN_BRACKET:
     734        4708 :         if (lexeme_ring_buffer_empty(&parser->buffer))
     735           0 :             return PARSER_ERROR(parser, "Section names can´t be empty");
     736             : 
     737        4708 :         config_from_parser(parser)->opened_brackets++;
     738             : 
     739        4708 :         return parse_section;
     740             : 
     741       19959 :     case LEXEME_LINEFEED:
     742       19959 :         if (!lexeme_ring_buffer_empty(&parser->buffer))
     743        1176 :             return parse_section_shorthand;
     744             : 
     745       18783 :         return parse_config;
     746             : 
     747       23641 :     case LEXEME_STRING:
     748       23641 :         if (!lexeme_ring_buffer_try_put(&parser->buffer, lexeme))
     749           0 :             return INTERNAL_ERROR(parser, "could not store string in ring buffer");
     750             : 
     751       23641 :         return parse_config;
     752             : 
     753        5931 :     case LEXEME_CLOSE_BRACKET:
     754        5931 :         return parse_section_end;
     755             : 
     756         356 :     case LEXEME_EOF:
     757         356 :         if (config_from_parser(parser)->opened_brackets)
     758           0 :             return PARSER_ERROR(parser, "EOF while looking for a close bracket");
     759             : 
     760         356 :         if (!lexeme_ring_buffer_empty(&parser->buffer))
     761           0 :             return INTERNAL_ERROR(parser, "premature EOF");
     762             : 
     763         356 :         break;
     764             : 
     765           0 :     case LEXEME_VARIABLE:
     766             :     case LEXEME_VARIABLE_DEFAULT:
     767           0 :         return PARSER_ERROR(parser, "Variable '%.*s' can't be used here",
     768             :                             (int)lexeme->value.len, lexeme->value.value);
     769             : 
     770             :     case TOTAL_LEXEMES:
     771             :         __builtin_unreachable();
     772             :     }
     773             : 
     774         356 :     return NULL;
     775             : }
     776             : 
     777       22297 : static const struct config_line *parser_next(struct parser *parser)
     778             : {
     779      104613 :     while (parser->state) {
     780             :         const struct config_line *line;
     781             : 
     782      104257 :         if ((line = config_ring_buffer_get_ptr_or_null(&parser->items)))
     783       21941 :             return line;
     784             : 
     785       82316 :         lwan_strbuf_reset(&parser->strbuf);
     786             : 
     787       82316 :         parser->state = parser->state(parser);
     788             :     }
     789             : 
     790         356 :     return config_ring_buffer_get_ptr_or_null(&parser->items);
     791             : }
     792             : 
     793             : static struct config *
     794          95 : config_open_path(const char *path, void **data, size_t *size)
     795             : {
     796             :     struct config *config;
     797             :     struct stat st;
     798             :     void *mapped;
     799             :     int fd;
     800             : 
     801          95 :     fd = open(path, O_RDONLY | O_CLOEXEC);
     802          95 :     if (fd < 0) {
     803           0 :         lwan_status_perror("Could not open configuration file: %s", path);
     804           0 :         return NULL;
     805             :     }
     806             : 
     807          95 :     if (fstat(fd, &st) < 0) {
     808           0 :         close(fd);
     809           0 :         return NULL;
     810             :     }
     811             : 
     812          95 :     mapped = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
     813          95 :     close(fd);
     814          95 :     if (mapped == MAP_FAILED)
     815           0 :         return NULL;
     816             : 
     817          95 :     config = malloc(sizeof(*config));
     818          95 :     if (!config) {
     819           0 :         munmap(mapped, (size_t)st.st_size);
     820           0 :         return NULL;
     821             :     }
     822             : 
     823          95 :     *data = config->mapped.addr = mapped;
     824          95 :     *size = config->mapped.sz = (size_t)st.st_size;
     825             : 
     826          95 :     return config;
     827             : }
     828             : 
     829             : static struct config *
     830          95 : config_init_data(struct config *config, const void *data, size_t len)
     831             : {
     832          95 :     config->parser = (struct parser){
     833             :         .state = parse_config,
     834             :         .lexer =
     835             :             {
     836             :                 .state = lex_config,
     837             :                 .pos = data,
     838             :                 .start = data,
     839          95 :                 .end = (char *)data + len,
     840             :                 .cur_line = 1,
     841             :             },
     842             :     };
     843             : 
     844          95 :     config->error_message = NULL;
     845          95 :     config->opened_brackets = 0;
     846             : 
     847          95 :     lwan_strbuf_init(&config->parser.strbuf);
     848          95 :     config_ring_buffer_init(&config->parser.items);
     849          95 :     lexeme_ring_buffer_init(&config->parser.buffer);
     850             : 
     851          95 :     return config;
     852             : }
     853             : 
     854          95 : struct config *config_open(const char *path)
     855             : {
     856             :     struct config *config;
     857             :     void *data;
     858             :     size_t len;
     859             : 
     860          95 :     config = config_open_path(path, &data, &len);
     861          95 :     return config ? config_init_data(config, data, len) : NULL;
     862             : }
     863             : 
     864             : #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
     865             : struct config *config_open_for_fuzzing(const uint8_t *data, size_t len)
     866             : {
     867             :     struct config *config = malloc(sizeof(*config));
     868             : 
     869             :     if (config) {
     870             :         config->mapped.addr = NULL;
     871             :         config->mapped.sz = 0;
     872             : 
     873             :         return config_init_data(config, data, len - 1);
     874             :     }
     875             : 
     876             :     return NULL;
     877             : }
     878             : #endif
     879             : 
     880        2054 : void config_close(struct config *config)
     881             : {
     882        2054 :     if (!config)
     883           0 :         return;
     884             : 
     885             : #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
     886        2054 :     if (config->mapped.addr)
     887          95 :         munmap(config->mapped.addr, config->mapped.sz);
     888             : #endif
     889             : 
     890        2054 :     free(config->error_message);
     891        2054 :     lwan_strbuf_free(&config->parser.strbuf);
     892        2054 :     free(config);
     893             : }
     894             : 
     895       12058 : const struct config_line *config_read_line(struct config *conf)
     896             : {
     897       12058 :     return conf->error_message ? NULL : parser_next(&conf->parser);
     898             : }
     899             : 
     900        2742 : static bool find_section_end(struct config *config)
     901             : {
     902             :     const struct config_line *line;
     903        2742 :     int cur_level = 1;
     904             : 
     905        2742 :     if (config->error_message)
     906           0 :         return false;
     907             : 
     908       10239 :     while ((line = parser_next(&config->parser))) {
     909       10239 :         if (line->type == CONFIG_LINE_TYPE_SECTION) {
     910        1566 :             cur_level++;
     911        8673 :         } else if (line->type == CONFIG_LINE_TYPE_SECTION_END) {
     912        4308 :             cur_level--;
     913             : 
     914        4308 :             if (!cur_level)
     915        2742 :                 return true;
     916             :         }
     917             :     }
     918             : 
     919           0 :     return false;
     920             : }
     921             : 
     922        1959 : struct config *config_isolate_section(struct config *current_conf,
     923             :                                       const struct config_line *current_line)
     924             : {
     925             :     struct lexer *lexer;
     926             :     struct config *isolated;
     927             :     const char *pos;
     928             : 
     929        1959 :     if (current_line->type != CONFIG_LINE_TYPE_SECTION)
     930           0 :         return NULL;
     931             : 
     932        1959 :     isolated = malloc(sizeof(*isolated));
     933        1959 :     if (!isolated)
     934           0 :         return NULL;
     935             : 
     936        1959 :     memcpy(isolated, current_conf, sizeof(*isolated));
     937        1959 :     lwan_strbuf_init(&isolated->parser.strbuf);
     938             : 
     939        1959 :     isolated->mapped.addr = NULL;
     940        1959 :     isolated->mapped.sz = 0;
     941             :     /* Keep opened_brackets from the original */
     942             : 
     943        1959 :     lexer = &isolated->parser.lexer;
     944        1959 :     lexer->start = lexer->pos;
     945             : 
     946        1959 :     pos = isolated->parser.lexer.pos;
     947        1959 :     if (!find_section_end(isolated)) {
     948           0 :         lwan_strbuf_free(&isolated->parser.strbuf);
     949           0 :         free(isolated);
     950             : 
     951           0 :         config_error(current_conf,
     952             :                      "Could not find section end while trying to isolate");
     953             : 
     954           0 :         return NULL;
     955             :     }
     956             : 
     957        1959 :     lexer->end = lexer->pos;
     958        1959 :     lexer->start = lexer->pos = pos;
     959             : 
     960        1959 :     return isolated;
     961             : }
     962             : 
     963         783 : bool config_skip_section(struct config *conf, const struct config_line *line)
     964             : {
     965         783 :     if (line->type != CONFIG_LINE_TYPE_SECTION)
     966           0 :         return false;
     967             : 
     968         783 :     return find_section_end(conf);
     969             : }
     970             : 
     971         356 : const char *config_last_error(struct config *conf)
     972             : {
     973         356 :     return conf->error_message;
     974             : }
     975             : 
     976           0 : int config_cur_line(struct config *conf)
     977             : {
     978           0 :     return conf->parser.lexer.cur_line;
     979             : }

Generated by: LCOV version 1.15-2-gb9d6727