Coverage Report

Created: 2023-06-07 06:46

/src/sudo/lib/util/parseln.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * SPDX-License-Identifier: ISC
3
 *
4
 * Copyright (c) 2007, 2013-2016 Todd C. Miller <Todd.Miller@sudo.ws>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/*
20
 * This is an open source non-commercial project. Dear PVS-Studio, please check it.
21
 * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
22
 */
23
24
#include <config.h>
25
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <ctype.h>
30
#ifdef HAVE_STDBOOL_H
31
# include <stdbool.h>
32
#else
33
# include "compat/stdbool.h"
34
#endif
35
36
#include "sudo_compat.h"
37
#include "sudo_util.h"
38
#include "sudo_debug.h"
39
40
/*
41
 * Read a line of input, honoring line continuation chars.
42
 * Remove comments and strip off leading and trailing spaces.
43
 * Returns the line length and updates the buf and bufsize pointers.
44
 * XXX - just use a struct w/ state, including getdelim buffer?
45
 *       could also make comment char and line continuation configurable
46
 */
47
ssize_t
48
sudo_parseln_v2(char **bufp, size_t *bufsizep, unsigned int *lineno, FILE *fp, int flags)
49
62.5k
{
50
62.5k
    size_t linesize = 0, total = 0;
51
62.5k
    ssize_t len;
52
62.5k
    char *cp, *line = NULL;
53
62.5k
    bool continued, comment;
54
62.5k
    debug_decl(sudo_parseln, SUDO_DEBUG_UTIL);
55
56
62.5k
    do {
57
62.5k
  comment = false;
58
62.5k
  continued = false;
59
62.5k
  len = getdelim(&line, &linesize, '\n', fp);
60
62.5k
  if (len == -1)
61
37.1k
      break;
62
25.4k
  if (lineno != NULL)
63
0
      (*lineno)++;
64
65
  /* Remove trailing newline(s) if present. */
66
50.8k
  while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
67
25.4k
      line[--len] = '\0';
68
69
  /* Remove comments or check for line continuation (but not both) */
70
25.4k
  if ((cp = strchr(line, '#')) != NULL) {
71
0
      if (cp == line || !ISSET(flags, PARSELN_COMM_BOL)) {
72
0
    *cp = '\0';
73
0
    len = (ssize_t)(cp - line);
74
0
    comment = true;
75
0
      }
76
0
  }
77
25.4k
  if (!comment && !ISSET(flags, PARSELN_CONT_IGN)) {
78
0
      if (len > 0 && line[len - 1] == '\\' && (len == 1 || line[len - 2] != '\\')) {
79
0
    line[--len] = '\0';
80
0
    continued = true;
81
0
      }
82
0
  }
83
84
  /* Trim leading and trailing whitespace */
85
25.4k
  if (!continued) {
86
25.4k
      while (len > 0 && isblank((unsigned char)line[len - 1]))
87
0
    line[--len] = '\0';
88
25.4k
  }
89
25.4k
  for (cp = line; isblank((unsigned char)*cp); cp++)
90
0
      len--;
91
92
25.4k
  if (*bufp == NULL || total + len >= *bufsizep) {
93
25.4k
      void *tmp;
94
25.4k
      size_t size = total + len + 1;
95
96
25.4k
      if (size < 64) {
97
0
    size = 64;
98
25.4k
      } else if (size <= 0x80000000) {
99
    /* Round up to next highest power of two. */
100
25.4k
    size--;
101
25.4k
    size |= size >> 1;
102
25.4k
    size |= size >> 2;
103
25.4k
    size |= size >> 4;
104
25.4k
    size |= size >> 8;
105
25.4k
    size |= size >> 16;
106
25.4k
    size++;
107
25.4k
      }
108
25.4k
      if ((tmp = realloc(*bufp, size)) == NULL) {
109
0
    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
110
0
        "unable to allocate memory");
111
0
    len = -1;
112
0
    total = 0;
113
0
    break;
114
0
      }
115
25.4k
      *bufp = tmp;
116
25.4k
      *bufsizep = size;
117
25.4k
  }
118
25.4k
  memcpy(*bufp + total, cp, len + 1);
119
25.4k
  total += len;
120
25.4k
    } while (continued);
121
0
    free(line);
122
62.5k
    if (len == -1 && total == 0)
123
37.1k
  debug_return_ssize_t(-1);
124
25.4k
    debug_return_ssize_t(total);
125
25.4k
}
126
127
ssize_t
128
sudo_parseln_v1(char **bufp, size_t *bufsizep, unsigned int *lineno, FILE *fp)
129
0
{
130
0
    return sudo_parseln_v2(bufp, bufsizep, lineno, fp, 0);
131
0
}