Bug Summary

File:src/usr.bin/vi/build/../vi/v_increment.c
Warning:line 237, column 2
Value stored to 'nret' is never read

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 v_increment.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/vi/build/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/vi/build -I /usr/src/usr.bin/vi/build/../include -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/vi/build/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/vi/build/../vi/v_increment.c
1/* $OpenBSD: v_increment.c,v 1.9 2016/01/06 22:28:52 millert Exp $ */
2
3/*-
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1992, 1993, 1994, 1995, 1996
7 * Keith Bostic. All rights reserved.
8 *
9 * See the LICENSE file for redistribution information.
10 */
11
12#include "config.h"
13
14#include <sys/types.h>
15#include <sys/queue.h>
16#include <sys/time.h>
17
18#include <bitstring.h>
19#include <ctype.h>
20#include <errno(*__errno()).h>
21#include <limits.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include "../common/common.h"
27#include "vi.h"
28
29static char * const fmt[] = {
30#define DEC0 0
31 "%ld",
32#define SDEC1 1
33 "%+ld",
34#define HEXC2 2
35 "0X%0*lX",
36#define HEXL3 3
37 "0x%0*lx",
38#define OCTAL4 4
39 "%#0*lo",
40};
41
42static void inc_err(SCR *, enum nresult);
43
44/*
45 * v_increment -- [count]#[#+-]
46 * Increment/decrement a keyword number.
47 *
48 * PUBLIC: int v_increment(SCR *, VICMD *);
49 */
50int
51v_increment(SCR *sp, VICMD *vp)
52{
53 enum nresult nret;
54 u_long ulval;
55 long change, ltmp, lval;
56 size_t beg, blen, end, len, nlen, wlen;
57 int base, isempty, rval;
58 char *bp, *ntype, *p, *t, nbuf[100];
59
60 /* Validate the operator. */
61 if (vp->character == '#')
62 vp->character = '+';
63 if (vp->character != '+' && vp->character != '-') {
64 v_emsg(sp, vp->kp->usage, VIM_USAGE);
65 return (1);
66 }
67
68 /* If new value set, save it off, but it has to fit in a long. */
69 if (F_ISSET(vp, VC_C1SET)(((vp)->flags) & ((0x00000800)))) {
70 if (vp->count > LONG_MAX9223372036854775807L) {
71 inc_err(sp, NUM_OVER);
72 return (1);
73 }
74 change = vp->count;
75 } else
76 change = 1;
77
78 /* Get the line. */
79 if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
80 if (isempty)
81 goto nonum;
82 return (1);
83 }
84
85 /*
86 * Skip any leading space before the number. Getting a cursor word
87 * implies moving the cursor to its beginning, if we moved, refresh
88 * now.
89 */
90 for (beg = vp->m_start.cno; beg < len && isspace(p[beg]); ++beg);
91 if (beg >= len)
92 goto nonum;
93 if (beg != vp->m_start.cno) {
94 sp->cno = beg;
95 (void)vs_refresh(sp, 0);
96 }
97
98#undef ishex
99#define ishex(c)(isdigit(c) || strchr("abcdefABCDEF", (c))) (isdigit(c) || strchr("abcdefABCDEF", (c)))
100#undef isoctal
101#define isoctal(c)(isdigit(c) && (c) != '8' && (c) != '9') (isdigit(c) && (c) != '8' && (c) != '9')
102
103 /*
104 * Look for 0[Xx], or leading + or - signs, guess at the base.
105 * The character after that must be a number. Wlen is set to
106 * the remaining characters in the line that could be part of
107 * the number.
108 */
109 wlen = len - beg;
110 if (p[beg] == '0' && wlen > 2 &&
111 (p[beg + 1] == 'X' || p[beg + 1] == 'x')) {
112 base = 16;
113 end = beg + 2;
114 if (!ishex(p[end])(isdigit(p[end]) || strchr("abcdefABCDEF", (p[end]))))
115 goto decimal;
116 ntype = p[beg + 1] == 'X' ? fmt[HEXC2] : fmt[HEXL3];
117 } else if (p[beg] == '0' && wlen > 1) {
118 base = 8;
119 end = beg + 1;
120 if (!isoctal(p[end])(isdigit(p[end]) && (p[end]) != '8' && (p[end
]) != '9')
)
121 goto decimal;
122 ntype = fmt[OCTAL4];
123 } else if (wlen >= 1 && (p[beg] == '+' || p[beg] == '-')) {
124 base = 10;
125 end = beg + 1;
126 ntype = fmt[SDEC1];
127 if (!isdigit(p[end]))
128 goto nonum;
129 } else {
130decimal: base = 10;
131 end = beg;
132 ntype = fmt[DEC0];
133 if (!isdigit(p[end])) {
134nonum: msgq(sp, M_ERR, "Cursor not in a number");
135 return (1);
136 }
137 }
138
139 /* Find the end of the word, possibly correcting the base. */
140 while (++end < len) {
141 switch (base) {
142 case 8:
143 if (isoctal(p[end])(isdigit(p[end]) && (p[end]) != '8' && (p[end
]) != '9')
)
144 continue;
145 if (p[end] == '8' || p[end] == '9') {
146 base = 10;
147 ntype = fmt[DEC0];
148 continue;
149 }
150 break;
151 case 10:
152 if (isdigit(p[end]))
153 continue;
154 break;
155 case 16:
156 if (ishex(p[end])(isdigit(p[end]) || strchr("abcdefABCDEF", (p[end]))))
157 continue;
158 break;
159 default:
160 abort();
161 /* NOTREACHED */
162 }
163 break;
164 }
165 wlen = (end - beg);
166
167 /*
168 * XXX
169 * If the line was at the end of the buffer, we have to copy it
170 * so we can guarantee that it's NULL-terminated. We make the
171 * buffer big enough to fit the line changes as well, and only
172 * allocate once.
173 */
174 GET_SPACE_RET(sp, bp, blen, len + 50){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp
; if (L__gp == ((void *)0) || (((L__gp)->flags) & ((0x0100
)))) { (bp) = ((void *)0); (blen) = 0; { void *L__bincp; if (
((len + 50)) > ((blen))) { if ((L__bincp = binc(((sp)), ((
bp)), &((blen)), ((len + 50)))) == ((void *)0)) return (1
); ((bp)) = L__bincp; } }; } else { { void *L__bincp; if (((len
+ 50)) > (L__gp->tmp_blen)) { if ((L__bincp = binc(((sp
)), (L__gp->tmp_bp), &(L__gp->tmp_blen), ((len + 50
)))) == ((void *)0)) return (1); (L__gp->tmp_bp) = L__bincp
; } }; (bp) = L__gp->tmp_bp; (blen) = L__gp->tmp_blen; (
((L__gp)->flags) |= ((0x0100))); } }
;
175 if (end == len) {
176 memmove(bp, &p[beg], wlen);
177 bp[wlen] = '\0';
178 t = bp;
179 } else
180 t = &p[beg];
181
182 /*
183 * Octal or hex deal in unsigned longs, everything else is done
184 * in signed longs.
185 */
186 if (base == 10) {
187 if ((nret = nget_slong(&lval, t, NULL((void *)0), 10)) != NUM_OK)
188 goto err;
189 ltmp = vp->character == '-' ? -change : change;
190 if (lval > 0 && ltmp > 0 && !NPFITS(LONG_MAX, lval, ltmp)(((unsigned long)(9223372036854775807L)) - (lval) >= (ltmp
))
) {
191 nret = NUM_OVER;
192 goto err;
193 }
194 if (lval < 0 && ltmp < 0 && !NNFITS(LONG_MIN, lval, ltmp)(((long)((-9223372036854775807L -1L))) - (lval) <= (ltmp))) {
195 nret = NUM_UNDER;
196 goto err;
197 }
198 lval += ltmp;
199 /* If we cross 0, signed numbers lose their sign. */
200 if (lval == 0 && ntype == fmt[SDEC1])
201 ntype = fmt[DEC0];
202 nlen = snprintf(nbuf, sizeof(nbuf), ntype, lval);
203 if (nlen >= sizeof(nbuf))
204 nlen = sizeof(nbuf) - 1;
205 } else {
206 if ((nret = nget_uslong(&ulval, t, NULL((void *)0), base)) != NUM_OK)
207 goto err;
208 if (vp->character == '+') {
209 if (!NPFITS(ULONG_MAX, ulval, change)(((unsigned long)((9223372036854775807L *2UL+1UL))) - (ulval)
>= (change))
) {
210 nret = NUM_OVER;
211 goto err;
212 }
213 ulval += change;
214 } else {
215 if (ulval < change) {
216 nret = NUM_UNDER;
217 goto err;
218 }
219 ulval -= change;
220 }
221
222 /* Correct for literal "0[Xx]" in format. */
223 if (base == 16)
224 wlen -= 2;
225
226 nlen = snprintf(nbuf, sizeof(nbuf), ntype, wlen, ulval);
227 if (nlen >= sizeof(nbuf))
228 nlen = sizeof(nbuf) - 1;
229 }
230
231 /* Build the new line. */
232 memmove(bp, p, beg);
233 memmove(bp + beg, nbuf, nlen);
234 memmove(bp + beg + nlen, p + end, len - beg - (end - beg));
235 len = beg + nlen + (len - beg - (end - beg));
236
237 nret = NUM_OK;
Value stored to 'nret' is never read
238 rval = db_set(sp, vp->m_start.lno, bp, len);
239
240 if (0) {
241err: rval = 1;
242 inc_err(sp, nret);
243 }
244 if (bp != NULL((void *)0))
245 FREE_SPACE(sp, bp, blen){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp
; if (L__gp != ((void *)0) && (bp) == L__gp->tmp_bp
) (((L__gp)->flags) &= ~((0x0100))); else free(bp); }
;
246 return (rval);
247}
248
249static void
250inc_err(SCR *sp, enum nresult nret)
251{
252 switch (nret) {
253 case NUM_ERR:
254 break;
255 case NUM_OK:
256 abort();
257 /* NOREACHED */
258 case NUM_OVER:
259 msgq(sp, M_ERR, "Resulting number too large");
260 break;
261 case NUM_UNDER:
262 msgq(sp, M_ERR, "Resulting number too small");
263 break;
264 }
265}