Bug Summary

File:src/bin/ed/re.c
Warning:line 116, column 2
Null pointer passed as 1st argument to memory 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 re.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/bin/ed/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/bin/ed/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/bin/ed/re.c
1/* $OpenBSD: re.c,v 1.19 2018/06/19 12:36:18 martijn Exp $ */
2/* $NetBSD: re.c,v 1.14 1995/03/21 09:04:48 cgd Exp $ */
3
4/* re.c: This file contains the regular expression interface routines for
5 the ed line editor. */
6/*-
7 * Copyright (c) 1993 Andrew Moore, Talke Studio.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <regex.h>
33#include <signal.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38#include "ed.h"
39
40static char *extract_pattern(int);
41static char *parse_char_class(char *);
42
43extern int patlock;
44
45
46/* get_compiled_pattern: return pointer to compiled pattern from command
47 buffer */
48regex_t *
49get_compiled_pattern(void)
50{
51 static regex_t *exp = NULL((void *)0);
52 char errbuf[128] = "";
53
54 char *exps;
55 char delimiter;
56 int n;
57
58 if ((delimiter = *ibufp) == ' ') {
1
Assuming the condition is false
2
Taking false branch
59 seterrmsg("invalid pattern delimiter");
60 return NULL((void *)0);
61 } else if (delimiter == '\n' || *++ibufp == '\n' || *ibufp == delimiter) {
3
Assuming the condition is false
4
Assuming the condition is false
5
Assuming the condition is false
6
Taking false branch
62 if (!exp)
63 seterrmsg("no previous pattern");
64 return exp;
65 } else if ((exps = extract_pattern(delimiter)) == NULL((void *)0))
7
Calling 'extract_pattern'
66 return NULL((void *)0);
67 /* buffer alloc'd && not reserved */
68 if (exp && !patlock)
69 regfree(exp);
70 else if ((exp = malloc(sizeof(regex_t))) == NULL((void *)0)) {
71 perror(NULL((void *)0));
72 seterrmsg("out of memory");
73 return NULL((void *)0);
74 }
75 patlock = 0;
76 if ((n = regcomp(exp, exps, 0)) != 0) {
77 regerror(n, exp, errbuf, sizeof errbuf);
78 seterrmsg(errbuf);
79 free(exp);
80 return exp = NULL((void *)0);
81 }
82 return exp;
83}
84
85
86/* extract_pattern: copy a pattern string from the command buffer; return
87 pointer to the copy */
88static char *
89extract_pattern(int delimiter)
90{
91 static char *lhbuf = NULL((void *)0); /* buffer */
8
'lhbuf' initialized to a null pointer value
92 static int lhbufsz = 0; /* buffer size */
93
94 char *nd;
95 int len;
96
97 for (nd = ibufp; *nd != delimiter && *nd != '\n'; nd++)
9
Loop condition is true. Entering loop body
14
Assuming the condition is false
98 switch (*nd) {
10
Control jumps to 'case 91:' at line 101
99 default:
100 break;
101 case '[':
102 if ((nd = parse_char_class(++nd)) == NULL((void *)0)) {
11
Assuming the condition is false
12
Taking false branch
103 seterrmsg("unbalanced brackets ([])");
104 return NULL((void *)0);
105 }
106 break;
13
Execution continues on line 97
107 case '\\':
108 if (*++nd == '\n') {
109 seterrmsg("trailing backslash (\\)");
110 return NULL((void *)0);
111 }
112 break;
113 }
114 len = nd - ibufp;
115 REALLOC(lhbuf, lhbufsz, len + 1, NULL)if ((len + 1) > (lhbufsz)) { int ti = (lhbufsz); char *ts;
mutex++; if ((ts = realloc((lhbuf), ti += (((len + 1)) > (
512) ? ((len + 1)) : (512)))) == ((void *)0)) { perror(((void
*)0)); seterrmsg("out of memory"); do { if (--mutex == 0) { if
(sighup) handle_hup(1); if (sigint) handle_int(2); } } while
(0); return ((void *)0); } (lhbufsz) = ti; (lhbuf) = ts; do {
if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint) handle_int
(2); } } while (0); }
;
15
Assuming the condition is false
16
Taking false branch
116 memcpy(lhbuf, ibufp, len);
17
Null pointer passed as 1st argument to memory copy function
117 lhbuf[len] = '\0';
118 ibufp = nd;
119 return (isbinary) ? NUL_TO_NEWLINE(lhbuf, len)translit_text(lhbuf, len, '\0', '\n') : lhbuf;
120}
121
122
123/* parse_char_class: expand a POSIX character class */
124static char *
125parse_char_class(char *s)
126{
127 int c, d;
128
129 if (*s == '^')
130 s++;
131 if (*s == ']')
132 s++;
133 for (; *s != ']' && *s != '\n'; s++)
134 if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '='))
135 for (s++, c = *++s; *s != ']' || c != d; s++)
136 if ((c = *s) == '\n')
137 return NULL((void *)0);
138 return (*s == ']') ? s : NULL((void *)0);
139}