Tue Aug 1 13:05:57 2023 UTC ()
Pull up following revision(s) (requested by riastradh in ticket #1868):

	sys/dev/spkr.c: revision 1.25 (patch)

spkr(4): Avoid some overflow issues.


(martin)
diff -r1.7 -r1.7.2.1 src/sys/dev/spkr.c

cvs diff -r1.7 -r1.7.2.1 src/sys/dev/spkr.c (expand / switch to unified diff)

--- src/sys/dev/spkr.c 2017/06/01 09:44:30 1.7
+++ src/sys/dev/spkr.c 2023/08/01 13:05:57 1.7.2.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: spkr.c,v 1.7 2017/06/01 09:44:30 pgoyette Exp $ */ 1/* $NetBSD: spkr.c,v 1.7.2.1 2023/08/01 13:05:57 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1990 Eric S. Raymond (esr@snark.thyrsus.com) 4 * Copyright (c) 1990 Eric S. Raymond (esr@snark.thyrsus.com)
5 * Copyright (c) 1990 Andrew A. Chernov (ache@astral.msk.su) 5 * Copyright (c) 1990 Andrew A. Chernov (ache@astral.msk.su)
6 * Copyright (c) 1990 Lennart Augustsson (lennart@augustsson.net) 6 * Copyright (c) 1990 Lennart Augustsson (lennart@augustsson.net)
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -33,27 +33,27 @@ @@ -33,27 +33,27 @@
33 * POSSIBILITY OF SUCH DAMAGE. 33 * POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35 35
36/* 36/*
37 * spkr.c -- device driver for console speaker on 80386 37 * spkr.c -- device driver for console speaker on 80386
38 * 38 *
39 * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990 39 * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
40 * modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su> 40 * modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su>
41 * 386bsd only clean version, all SYSV stuff removed 41 * 386bsd only clean version, all SYSV stuff removed
42 * use hz value from param.c 42 * use hz value from param.c
43 */ 43 */
44 44
45#include <sys/cdefs.h> 45#include <sys/cdefs.h>
46__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.7 2017/06/01 09:44:30 pgoyette Exp $"); 46__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.7.2.1 2023/08/01 13:05:57 martin Exp $");
47 47
48#include <sys/param.h> 48#include <sys/param.h>
49#include <sys/systm.h> 49#include <sys/systm.h>
50#include <sys/kernel.h> 50#include <sys/kernel.h>
51#include <sys/errno.h> 51#include <sys/errno.h>
52#include <sys/device.h> 52#include <sys/device.h>
53#include <sys/malloc.h> 53#include <sys/malloc.h>
54#include <sys/module.h> 54#include <sys/module.h>
55#include <sys/uio.h> 55#include <sys/uio.h>
56#include <sys/proc.h> 56#include <sys/proc.h>
57#include <sys/ioctl.h> 57#include <sys/ioctl.h>
58#include <sys/conf.h> 58#include <sys/conf.h>
59 59
@@ -154,51 +154,56 @@ playtone(struct spkr_softc *sc, int pitc @@ -154,51 +154,56 @@ playtone(struct spkr_softc *sc, int pitc
154 int sound, silence, snum = 1, sdenom = 1; 154 int sound, silence, snum = 1, sdenom = 1;
155 155
156 /* this weirdness avoids floating-point arithmetic */ 156 /* this weirdness avoids floating-point arithmetic */
157 for (; sustain; sustain--) { 157 for (; sustain; sustain--) {
158 snum *= NUM_MULT; 158 snum *= NUM_MULT;
159 sdenom *= DENOM_MULT; 159 sdenom *= DENOM_MULT;
160 } 160 }
161 161
162 if (pitch == -1) { 162 if (pitch == -1) {
163 (*sc->sc_rest)(sc->sc_dev, sc->sc_whole 163 (*sc->sc_rest)(sc->sc_dev, sc->sc_whole
164 * snum / (val * sdenom)); 164 * snum / (val * sdenom));
165 return; 165 return;
166 } 166 }
 167 KASSERTMSG(pitch < __arraycount(pitchtab), "pitch=%d", pitch);
167 168
168 int fac = sc->sc_whole * (FILLTIME - sc->sc_fill); 169 int fac = sc->sc_whole * (FILLTIME - sc->sc_fill);
169 int fval = FILLTIME * val; 170 int fval = FILLTIME * val;
170 sound = (sc->sc_whole * snum) / (val * sdenom) - fac / fval; 171 sound = (sc->sc_whole * snum) / (val * sdenom) - fac / fval;
171 silence = fac * snum / (fval * sdenom); 172 silence = fac * snum / (fval * sdenom);
172 173
173#ifdef SPKRDEBUG 174#ifdef SPKRDEBUG
174 aprint_debug_dev(sc->sc_dev, 175 aprint_debug_dev(sc->sc_dev,
175 "%s: pitch %d for %d ticks, rest for %d ticks\n", __func__, 176 "%s: pitch %d for %d ticks, rest for %d ticks\n", __func__,
176 pitch, sound, silence); 177 pitch, sound, silence);
177#endif /* SPKRDEBUG */ 178#endif /* SPKRDEBUG */
178 179
179 (*sc->sc_tone)(sc->sc_dev, pitchtab[pitch], sound); 180 (*sc->sc_tone)(sc->sc_dev, pitchtab[pitch], sound);
180 if (sc->sc_fill != LEGATO) 181 if (sc->sc_fill != LEGATO)
181 (*sc->sc_rest)(sc->sc_dev, silence); 182 (*sc->sc_rest)(sc->sc_dev, silence);
182} 183}
183 184
184/* interpret and play an item from a notation string */ 185/* interpret and play an item from a notation string */
185static void 186static void
186playstring(struct spkr_softc *sc, const char *cp, size_t slen) 187playstring(struct spkr_softc *sc, const char *cp, size_t slen)
187{ 188{
188 int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE; 189 int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
189 190
190#define GETNUM(cp, v) \ 191#define GETNUM(cp, v) \
191 for (v = 0; slen > 0 && isdigit((unsigned char)cp[1]); ) { \ 192 for (v = 0; slen > 0 && isdigit((unsigned char)cp[1]); ) { \
 193 if (v > INT_MAX/10 - (cp[1] - '0')) { \
 194 v = INT_MAX; \
 195 continue; \
 196 } \
192 v = v * 10 + (*++cp - '0'); \ 197 v = v * 10 + (*++cp - '0'); \
193 slen--; \ 198 slen--; \
194 } 199 }
195 200
196 for (; slen--; cp++) { 201 for (; slen--; cp++) {
197 int sustain, timeval, tempo; 202 int sustain, timeval, tempo;
198 char c = toupper((unsigned char)*cp); 203 char c = toupper((unsigned char)*cp);
199 204
200#ifdef SPKRDEBUG 205#ifdef SPKRDEBUG
201 aprint_debug_dev(sc->sc_dev, "%s: %c (%x)\n", __func__, c, c); 206 aprint_debug_dev(sc->sc_dev, "%s: %c (%x)\n", __func__, c, c);
202#endif /* SPKRDEBUG */ 207#endif /* SPKRDEBUG */
203 208
204 switch (c) { 209 switch (c) {
@@ -262,46 +267,51 @@ playstring(struct spkr_softc *sc, const  @@ -262,46 +267,51 @@ playstring(struct spkr_softc *sc, const
262 break; 267 break;
263 268
264 case 'O': 269 case 'O':
265 if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) { 270 if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) {
266 sc->sc_octprefix = sc->sc_octtrack = false; 271 sc->sc_octprefix = sc->sc_octtrack = false;
267 ++cp; 272 ++cp;
268 slen--; 273 slen--;
269 } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) { 274 } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) {
270 sc->sc_octtrack = true; 275 sc->sc_octtrack = true;
271 ++cp; 276 ++cp;
272 slen--; 277 slen--;
273 } else { 278 } else {
274 GETNUM(cp, sc->sc_octave); 279 GETNUM(cp, sc->sc_octave);
 280 KASSERTMSG(sc->sc_octave >= 0, "%d",
 281 sc->sc_octave);
275 if (sc->sc_octave >= NOCTAVES) 282 if (sc->sc_octave >= NOCTAVES)
276 sc->sc_octave = DFLT_OCTAVE; 283 sc->sc_octave = DFLT_OCTAVE;
277 sc->sc_octprefix = true; 284 sc->sc_octprefix = true;
278 } 285 }
279 break; 286 break;
280 287
281 case '>': 288 case '>':
282 if (sc->sc_octave < NOCTAVES - 1) 289 if (sc->sc_octave < NOCTAVES - 1)
283 sc->sc_octave++; 290 sc->sc_octave++;
284 sc->sc_octprefix = true; 291 sc->sc_octprefix = true;
285 break; 292 break;
286 293
287 case '<': 294 case '<':
288 if (sc->sc_octave > 0) 295 if (sc->sc_octave > 0)
289 sc->sc_octave--; 296 sc->sc_octave--;
290 sc->sc_octprefix = true; 297 sc->sc_octprefix = true;
291 break; 298 break;
292 299
293 case 'N': 300 case 'N':
294 GETNUM(cp, pitch); 301 GETNUM(cp, pitch);
 302 KASSERTMSG(pitch >= 0, "pitch=%d", pitch);
 303 if (pitch >= __arraycount(pitchtab))
 304 break;
295 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { 305 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
296 slen--; 306 slen--;
297 sustain++; 307 sustain++;
298 } 308 }
299 playtone(sc, pitch - 1, sc->sc_value, sustain); 309 playtone(sc, pitch - 1, sc->sc_value, sustain);
300 break; 310 break;
301 311
302 case 'L': 312 case 'L':
303 GETNUM(cp, sc->sc_value); 313 GETNUM(cp, sc->sc_value);
304 if (sc->sc_value <= 0 || sc->sc_value > MIN_VALUE) 314 if (sc->sc_value <= 0 || sc->sc_value > MIN_VALUE)
305 sc->sc_value = DFLT_VALUE; 315 sc->sc_value = DFLT_VALUE;
306 break; 316 break;
307 317