Bug Summary

File:backend/dvi/mdvi-lib/tfm.c
Warning:line 112, column 14
Access to field 'offset' results in a dereference of a null pointer (loaded from variable 'ch')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tfm.c -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 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/backend/dvi/mdvi-lib -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../../.. -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/backend/dvi/mdvi-lib -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-02-17-123548-54190-1 -x c tfm.c
1/*
2 * Copyright (C) 2000, Matias Atria
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#include <config.h>
20#include <stdlib.h>
21#include <stdarg.h>
22#include <string.h>
23#include <sys/stat.h>
24#include <unistd.h>
25
26#include "mdvi.h"
27#include "private.h"
28
29static int tfm_load_font __PROTO((DviParams *, DviFont *))(DviParams *, DviFont *);
30static int tfm_font_get_glyph __PROTO((DviParams *, DviFont *, int))(DviParams *, DviFont *, int);
31
32DviFontInfo tfm_font_info = {
33 "TFM",
34 0, /* scaling not supported by format */
35 tfm_load_font,
36 tfm_font_get_glyph,
37 mdvi_shrink_box,
38 mdvi_shrink_box,
39 NULL((void*)0), /* free */
40 NULL((void*)0), /* reset */
41 NULL((void*)0), /* lookup */
42 kpse_tfm_format,
43 NULL((void*)0)
44};
45
46DviFontInfo ofm_font_info = {
47 "OFM",
48 0, /* scaling not supported by format */
49 tfm_load_font,
50 tfm_font_get_glyph,
51 mdvi_shrink_box,
52 mdvi_shrink_box,
53 NULL((void*)0), /* free */
54 NULL((void*)0), /* reset */
55 NULL((void*)0), /* lookup */
56 kpse_ofm_format,
57 NULL((void*)0)
58};
59
60DviFontInfo afm_font_info = {
61 "AFM",
62 0, /* scaling not supported by format */
63 tfm_load_font,
64 tfm_font_get_glyph,
65 mdvi_shrink_box,
66 mdvi_shrink_box,
67 NULL((void*)0), /* free */
68 NULL((void*)0), /* reset */
69 NULL((void*)0), /* lookup */
70 kpse_afm_format,
71 NULL((void*)0)
72};
73
74#define TYPENAME(font)((font)->search.info ? (font)->search.info : "none") \
75 ((font)->search.info ? (font)->search.info : "none")
76
77/*
78 * Although it does not seem that way, this conversion is independent of the
79 * shrinking factors, within roundoff (that's because `conv' and `vconv'
80 * have already been scaled by hshrink and vshrink, repsectively). We
81 * should really use `dviconv' and `dvivconv', but I'm not so sure those
82 * should be moved to the DviParams structure.
83 */
84#define XCONV(x)(int)((params->conv * (x) * params->hshrink) + 0.5) FROUND(params->conv * (x) * params->hshrink)(int)((params->conv * (x) * params->hshrink) + 0.5)
85#define YCONV(y)(int)((params->vconv * (y) * params->vshrink) + 0.5) FROUND(params->vconv * (y) * params->vshrink)(int)((params->vconv * (y) * params->vshrink) + 0.5)
86
87/* this is used quite often in several places, so I made it standalone */
88int get_tfm_chars(DviParams *params, DviFont *font, TFMInfo *info, int loaded)
89{
90 Int32 z, alpha, beta;
91 int n;
92 DviFontChar *ch;
93 TFMChar *ptr;
94
95 n = info->hic - info->loc + 1;
96 if(n != FONT_GLYPH_COUNT(font)((font)->hic - (font)->loc + 1)) {
9
Assuming the condition is false
10
Taking false branch
97 font->chars = mdvi_realloc(font->chars,
98 n * sizeof(DviFontChar));
99 }
100 font->loc = info->loc;
101 font->hic = info->hic;
102 ch = font->chars;
11
Null pointer value stored to 'ch'
103 ptr = info->chars;
104
105 /* Prepare z, alpha and beta for TFM width computation */
106 TFMPREPARE(font->scale, z, alpha, beta)do { alpha = 16; z = (font->scale); while(z > 040000000L
) { z >>= 1; alpha <<= 1; } beta = 256 / alpha; alpha
*= z; } while(0)
;
12
Assuming 'z' is <= 8388608
13
Loop condition is false. Execution continues on line 106
14
Loop condition is false. Exiting loop
107
108 /* get the character metrics */
109 for(n = info->loc; n <= info->hic; ch++, ptr++, n++) {
15
Assuming 'n' is <= field 'hic'
16
Loop condition is true. Entering loop body
110 int a, b, c, d;
111
112 ch->offset = ptr->present;
17
Access to field 'offset' results in a dereference of a null pointer (loaded from variable 'ch')
113 if(ch->offset == 0)
114 continue;
115 /* this is what we came here for */
116 ch->tfmwidth = TFMSCALE(z, ptr->advance, alpha, beta)(((((ptr->advance) >> 24) & 0xff) == 255) ? ((((
((((ptr->advance)) & 0xff) * ((z))) >> 8) + ((((
(ptr->advance)) >> 8) & 0xff) * ((z)))) >>
8) + ((((ptr->advance)) >> 16) & 0xff) * ((z)))
/ (beta) - (alpha) : ((((((((ptr->advance)) & 0xff) *
((z))) >> 8) + (((((ptr->advance)) >> 8) &
0xff) * ((z)))) >> 8) + ((((ptr->advance)) >>
16) & 0xff) * ((z))) / (beta))
;
117 /* scale all other TFM units (so they are in DVI units) */
118 a = TFMSCALE(z, ptr->left, alpha, beta)(((((ptr->left) >> 24) & 0xff) == 255) ? (((((((
(ptr->left)) & 0xff) * ((z))) >> 8) + (((((ptr->
left)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr
->left)) >> 16) & 0xff) * ((z))) / (beta) - (alpha
) : ((((((((ptr->left)) & 0xff) * ((z))) >> 8) +
(((((ptr->left)) >> 8) & 0xff) * ((z)))) >>
8) + ((((ptr->left)) >> 16) & 0xff) * ((z))) / (
beta))
;
119 b = TFMSCALE(z, ptr->right, alpha, beta)(((((ptr->right) >> 24) & 0xff) == 255) ? ((((((
((ptr->right)) & 0xff) * ((z))) >> 8) + (((((ptr
->right)) >> 8) & 0xff) * ((z)))) >> 8) + (
(((ptr->right)) >> 16) & 0xff) * ((z))) / (beta)
- (alpha) : ((((((((ptr->right)) & 0xff) * ((z))) >>
8) + (((((ptr->right)) >> 8) & 0xff) * ((z)))) >>
8) + ((((ptr->right)) >> 16) & 0xff) * ((z))) /
(beta))
;
120 c = TFMSCALE(z, ptr->height, alpha, beta)(((((ptr->height) >> 24) & 0xff) == 255) ? (((((
(((ptr->height)) & 0xff) * ((z))) >> 8) + (((((ptr
->height)) >> 8) & 0xff) * ((z)))) >> 8) +
((((ptr->height)) >> 16) & 0xff) * ((z))) / (beta
) - (alpha) : ((((((((ptr->height)) & 0xff) * ((z))) >>
8) + (((((ptr->height)) >> 8) & 0xff) * ((z))))
>> 8) + ((((ptr->height)) >> 16) & 0xff) *
((z))) / (beta))
;
121 d = TFMSCALE(z, ptr->depth, alpha, beta)(((((ptr->depth) >> 24) & 0xff) == 255) ? ((((((
((ptr->depth)) & 0xff) * ((z))) >> 8) + (((((ptr
->depth)) >> 8) & 0xff) * ((z)))) >> 8) + (
(((ptr->depth)) >> 16) & 0xff) * ((z))) / (beta)
- (alpha) : ((((((((ptr->depth)) & 0xff) * ((z))) >>
8) + (((((ptr->depth)) >> 8) & 0xff) * ((z)))) >>
8) + ((((ptr->depth)) >> 16) & 0xff) * ((z))) /
(beta))
;
122
123 /* now convert to unscaled pixels */
124 ch->width = XCONV(b - a)(int)((params->conv * (b - a) * params->hshrink) + 0.5);
125 ch->height = YCONV(c - d)(int)((params->vconv * (c - d) * params->vshrink) + 0.5
)
;
126 if(ch->height < 0) ch->height = -ch->height;
127 ch->x = XCONV(a)(int)((params->conv * (a) * params->hshrink) + 0.5);
128 ch->y = YCONV(c)(int)((params->vconv * (c) * params->vshrink) + 0.5);
129 /*
130 * the offset is not used, but we might as well set it to
131 * something meaningful (and it MUST be non-zero)
132 */
133 ch->flags = 0;
134 ch->code = n;
135 ch->glyph.data = NULL((void*)0);
136 ch->grey.data = NULL((void*)0);
137 ch->shrunk.data = NULL((void*)0);
138 ch->loaded = loaded;
139 }
140
141 return 0;
142}
143
144/*
145 * We use this function as a last resort to find the character widths in a
146 * font The DVI rendering code can correctly skip over a glyph if it knows
147 * its TFM width, which is what we try to find here.
148 */
149static int tfm_load_font(DviParams *params, DviFont *font)
150{
151 TFMInfo *tfm;
152 int type;
153
154 switch(font->search.info->kpse_type) {
1
Control jumps to 'case kpse_ofm_format:' at line 161
155 case kpse_tfm_format:
156 type = DviFontTFM;
157 break;
158 case kpse_afm_format:
159 type = DviFontAFM;
160 break;
161 case kpse_ofm_format:
162 type = DviFontOFM;
163 break;
164 default:
165 return -1;
166 }
167
168 /* we don't need this */
169 if(font->in) {
2
Execution continues on line 169
3
Assuming field 'in' is null
4
Taking false branch
170 fclosekpse_fclose_trace(font->in);
171 font->in = NULL((void*)0);
172 }
173 tfm = get_font_metrics(font->fontname, type, font->filename);
174 if(tfm == NULL((void*)0))
5
Assuming 'tfm' is not equal to NULL
175 return -1;
176
177 if(tfm->checksum && font->checksum && tfm->checksum != font->checksum) {
6
Assuming field 'checksum' is 0
178 mdvi_warning(_("%s: Checksum mismatch (got %u, expected %u)\n")gettext("%s: Checksum mismatch (got %u, expected %u)\n"),
179 font->fontname, (unsigned)tfm->checksum,
180 (unsigned)font->checksum);
181 }
182 font->checksum = tfm->checksum;
183 font->design = tfm->design;
184 font->loc = 0;
185 font->hic = 0;
186 font->chars = NULL((void*)0);
7
Null pointer value stored to field 'chars'
187 get_tfm_chars(params, font, tfm, 1);
8
Calling 'get_tfm_chars'
188
189 /* free everything */
190 free_font_metrics(tfm);
191
192 return 0;
193}
194
195static int tfm_font_get_glyph(DviParams *params, DviFont *font, int code)
196{
197 DviFontChar *ch;
198
199 ch = FONTCHAR(font, code)(((code) < font->loc || (code) > font->hic || !(font
)->chars) ? ((void*)0) : &font->chars[(code) - (font
)->loc])
;
200 if(!glyph_present(ch)((ch) && (ch)->offset))
201 return -1;
202 ch->glyph.x = ch->x;
203 ch->glyph.y = ch->y;
204 ch->glyph.w = ch->width;
205 ch->glyph.h = ch->height;
206 /*
207 * This has two purposes: (1) avoid unnecessary calls to this function,
208 * and (2) detect when the glyph data for a TFM font is actually used
209 * (we'll get a SEGV). Any occurrence of that is a bug.
210 */
211 ch->glyph.data = MDVI_GLYPH_EMPTY((void *)1);
212
213 return 0;
214}