Bug Summary

File:src/usr.bin/lex/regex.c
Warning:line 93, column 2
Null pointer passed as 1st argument to string copy function

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name regex.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/lex/obj -resource-dir /usr/local/lib/clang/13.0.0 -I . -I /usr/src/usr.bin/lex -D HAVE_CONFIG_H -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/lex/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/lex/regex.c
1/* $OpenBSD: regex.c,v 1.3 2015/11/19 23:20:34 tedu Exp $ */
2
3/** regex - regular expression functions related to POSIX regex lib. */
4
5/* This file is part of flex. */
6
7/* Redistribution and use in source and binary forms, with or without */
8/* modification, are permitted provided that the following conditions */
9/* are met: */
10
11/* 1. Redistributions of source code must retain the above copyright */
12/* notice, this list of conditions and the following disclaimer. */
13/* 2. Redistributions in binary form must reproduce the above copyright */
14/* notice, this list of conditions and the following disclaimer in the */
15/* documentation and/or other materials provided with the distribution. */
16
17/* Neither the name of the University nor the names of its contributors */
18/* may be used to endorse or promote products derived from this software */
19/* without specific prior written permission. */
20
21/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
22/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
23/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
24/* PURPOSE. */
25
26#include "flexdef.h"
27
28
29static const char* REGEXP_LINEDIR = "^#line ([[:digit:]]+) \"(.*)\"";
30static const char* REGEXP_BLANK_LINE = "^[[:space:]]*$";
31
32regex_t regex_linedir; /**< matches line directives */
33regex_t regex_blank_line; /**< matches blank lines */
34
35
36/** Initialize the regular expressions.
37 * @return true upon success.
38 */
39bool_Bool flex_init_regex(void)
40{
41 flex_regcomp(&regex_linedir, REGEXP_LINEDIR, REG_EXTENDED0001);
42 flex_regcomp(&regex_blank_line, REGEXP_BLANK_LINE, REG_EXTENDED0001);
43
44 return true1;
45}
46
47/** Compiles a regular expression or dies trying.
48 * @param preg Same as for regcomp().
49 * @param regex Same as for regcomp().
50 * @param cflags Same as for regcomp().
51 */
52void flex_regcomp(regex_t *preg, const char *regex, int cflags)
53{
54 int err;
55
56 memset (preg, 0, sizeof (regex_t));
57
58 if ((err = regcomp (preg, regex, cflags)) != 0) {
59 const int errbuf_sz = 200;
60 char *errbuf, *rxerr;
61
62 errbuf = (char*)malloc(errbuf_sz *sizeof(char));
63 if (!errbuf)
64 flexfatal(_("Unable to allocate buffer to report regcomp")"Unable to allocate buffer to report regcomp");
65 rxerr = (char*)malloc(errbuf_sz *sizeof(char));
66 if (!rxerr)
67 flexfatal(_("Unable to allocate buffer for regerror")"Unable to allocate buffer for regerror");
68 regerror (err, preg, rxerr, errbuf_sz);
69 snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr);
70
71 flexfatal (errbuf);
72 free(errbuf);
73 free(rxerr);
74 }
75}
76
77/** Extract a copy of the match, or NULL if no match.
78 * @param m A match as returned by regexec().
79 * @param src The source string that was passed to regexec().
80 * @return The allocated string.
81 */
82char *regmatch_dup (regmatch_t * m, const char *src)
83{
84 char *str;
85 int len;
86
87 if (m
6.1
'm' is not equal to NULL
== NULL((void *)0) || m->rm_so
6.2
Field 'rm_so' is >= 0
< 0)
7
Taking false branch
88 return NULL((void *)0);
89 len = m->rm_eo - m->rm_so;
90 str = (char *) malloc ((len + 1) * sizeof (char));
8
Value assigned to 'str'
91 if (!str)
9
Assuming 'str' is null
10
Taking true branch
92 flexfatal(_("Unable to allocate a copy of the match")"Unable to allocate a copy of the match");
93 strncpy (str, src + m->rm_so, len);
11
Null pointer passed as 1st argument to string copy function
94 str[len] = 0;
95 return str;
96}
97
98/** Copy the match.
99 * @param m A match as returned by regexec().
100 * @param dest The destination buffer.
101 * @param src The source string that was passed to regexec().
102 * @return dest
103 */
104char *regmatch_cpy (regmatch_t * m, char *dest, const char *src)
105{
106 if (m == NULL((void *)0) || m->rm_so < 0) {
107 if (dest)
108 dest[0] = '\0';
109 return dest;
110 }
111
112 snprintf (dest, regmatch_len(m), "%s", src + m->rm_so);
113 return dest;
114}
115
116/** Get the length in characters of the match.
117 * @param m A match as returned by regexec().
118 * @param src The source string that was passed to regexec().
119 * @return The length of the match.
120 */
121int regmatch_len (regmatch_t * m)
122{
123 if (m == NULL((void *)0) || m->rm_so < 0) {
124 return 0;
125 }
126
127 return m->rm_eo - m->rm_so;
128}
129
130
131
132/** Convert a regmatch_t object to an integer using the strtol() function.
133 * @param m A match as returned by regexec().
134 * @param src The source string that was passed to regexec().
135 * @param endptr Same as the second argument to strtol().
136 * @param base Same as the third argument to strtol().
137 * @return The converted integer or error (Return value is the same as for strtol()).
138 */
139int regmatch_strtol (regmatch_t * m, const char *src, char **endptr,
140 int base)
141{
142 int n = 0;
143
144#define bufsz20 20
145 char buf[bufsz20];
146 char *s;
147
148 if (m == NULL((void *)0) || m->rm_so < 0)
1
Assuming 'm' is not equal to NULL
2
Assuming field 'rm_so' is >= 0
3
Taking false branch
149 return 0;
150
151 if (regmatch_len (m) < bufsz20)
4
Assuming the condition is false
5
Taking false branch
152 s = regmatch_cpy (m, buf, src);
153 else
154 s = regmatch_dup (m, src);
6
Calling 'regmatch_dup'
155
156 n = strtol (s, endptr, base);
157
158 if (s != buf)
159 free (s);
160
161 return n;
162}
163
164/** Check for empty or non-existent match.
165 * @param m A match as returned by regexec().
166 * @return false if match length is non-zero.
167 * Note that reg_empty returns true even if match did not occur at all.
168 */
169bool_Bool regmatch_empty (regmatch_t * m)
170{
171 return (m == NULL((void *)0) || m->rm_so < 0 || m->rm_so == m->rm_eo);
172}