Bug Summary

File:jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c
Warning:line 127, column 13
Array access (from variable 'area') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name debug_mem.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 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -D __MEDIALIB_OLD_NAMES -D __USE_J2D_NAMES -D MLIB_NO_LIBSUNMATH -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/libawt -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/common/awt -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.desktop -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/awt/image -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/awt/image/cvutils -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/libawt/java2d -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d/loops -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d/pipe -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.base -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/awt/medialib -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/medialib -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libmlib_image -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/include -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/include -I /home/daniel/Projects/java/jdk/src/java.base/linux/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/include -I /home/daniel/Projects/java/jdk/src/java.base/share/native/include -D _FORTIFY_SOURCE=2 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-unused -Wno-sign-compare -Wno-unused-result -Wno-maybe-uninitialized -Wno-format-nonliteral -Wno-parentheses -Wno-unused-value -Wno-unused-function -std=c99 -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility default -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c /home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c
1/*
2 * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#if defined(DEBUG1)
27
28#include "debug_util.h"
29
30#define DMEM_MIN(a,b)(a) < (b) ? (a) : (b) (a) < (b) ? (a) : (b)
31#define DMEM_MAX(a,b)(a) > (b) ? (a) : (b) (a) > (b) ? (a) : (b)
32
33typedef char byte_t;
34
35static const byte_t ByteInited = '\xCD';
36static const byte_t ByteFreed = '\xDD';
37static const byte_t ByteGuard = '\xFD';
38
39enum {
40 MAX_LINENUM = 50000, /* I certainly hope we don't have source files bigger than this */
41 MAX_CHECK_BYTES = 27, /* max bytes to check at start of block */
42 MAX_GUARD_BYTES = 8, /* size of guard areas on either side of a block */
43 MAX_DECIMAL_DIGITS = 15
44};
45
46/* Debug Info Header to precede allocated block */
47typedef struct MemoryBlockHeader {
48 char filename[FILENAME_MAX4096+1]; /* filename where alloc occurred */
49 int linenumber; /* line where alloc occurred */
50 size_t size; /* size of the allocation */
51 int order; /* the order the block was allocated in */
52 struct MemoryListLink * listEnter; /* pointer to the free list node */
53 byte_t guard[MAX_GUARD_BYTES]; /* guard area for underrun check */
54} MemoryBlockHeader;
55
56/* Tail to follow allocated block */
57typedef struct MemoryBlockTail {
58 byte_t guard[MAX_GUARD_BYTES]; /* guard area overrun check */
59} MemoryBlockTail;
60
61/* Linked list of allocated memory blocks */
62typedef struct MemoryListLink {
63 struct MemoryListLink * next;
64 MemoryBlockHeader * header;
65 int freed;
66} MemoryListLink;
67
68/**************************************************
69 * Global Data structures
70 */
71static DMemState DMemGlobalState;
72extern const DMemState * DMemStatePtr = &DMemGlobalState;
73static MemoryListLink MemoryList = {NULL((void*)0),NULL((void*)0),FALSE0};
74static dmutex_t DMemMutex = NULL((void*)0);
75
76/**************************************************/
77
78/*************************************************
79 * Client callback invocation functions
80 */
81static void * DMem_ClientAllocate(size_t size) {
82 if (DMemGlobalState.pfnAlloc != NULL((void*)0)) {
83 return (*DMemGlobalState.pfnAlloc)(size);
84 }
85 return malloc(size);
86}
87
88static void DMem_ClientFree(void * ptr) {
89 if (DMemGlobalState.pfnFree != NULL((void*)0)) {
90 (*DMemGlobalState.pfnFree)(ptr);
91 }
92 free(ptr);
93}
94
95static dbool_t DMem_ClientCheckPtr(void * ptr, size_t size) {
96 if (DMemGlobalState.pfnCheckPtr != NULL((void*)0)) {
97 return (*DMemGlobalState.pfnCheckPtr)(ptr, size);
98 }
99 return ptr != NULL((void*)0);
100}
101
102/**************************************************/
103
104/*************************************************
105 * Debug Memory Manager implementation
106 */
107
108static MemoryListLink * DMem_TrackBlock(MemoryBlockHeader * header) {
109 MemoryListLink * link;
110
111 link = (MemoryListLink *)DMem_ClientAllocate(sizeof(MemoryListLink));
112 if (link != NULL((void*)0)) {
113 link->header = header;
114 link->header->listEnter = link;
115 link->next = MemoryList.next;
116 link->freed = FALSE0;
117 MemoryList.next = link;
118 }
119
120 return link;
121}
122
123static int DMem_VerifyGuardArea(const byte_t * area) {
124 int nbyte;
125
126 for ( nbyte = 0; nbyte < MAX_GUARD_BYTES; nbyte++ ) {
10
Loop condition is true. Entering loop body
127 if (area[nbyte] != ByteGuard) {
11
Array access (from variable 'area') results in a null pointer dereference
128 return FALSE0;
129 }
130 }
131 return TRUE1;
132}
133
134static void DMem_VerifyHeader(MemoryBlockHeader * header) {
135 DASSERTMSG( DMem_ClientCheckPtr(header, sizeof(MemoryBlockHeader)), "Invalid header" )if ( !(DMem_ClientCheckPtr(header, sizeof(MemoryBlockHeader))
) ) { DAssert_Impl( ("Invalid header"), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 135); } else { }
;
7
Taking true branch
136 DASSERTMSG( DMem_VerifyGuardArea(header->guard), "Header corruption, possible underwrite" )if ( !(DMem_VerifyGuardArea(header->guard)) ) { DAssert_Impl
( ("Header corruption, possible underwrite"), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 136); } else { }
;
8
Passing null pointer value via 1st parameter 'area'
9
Calling 'DMem_VerifyGuardArea'
137 DASSERTMSG( header->linenumber > 0 && header->linenumber < MAX_LINENUM, "Header corruption, bad line number" )if ( !(header->linenumber > 0 && header->linenumber
< MAX_LINENUM) ) { DAssert_Impl( ("Header corruption, bad line number"
), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 137); } else { }
;
138 DASSERTMSG( header->size <= DMemGlobalState.biggestBlock, "Header corruption, block size is too large")if ( !(header->size <= DMemGlobalState.biggestBlock) ) {
DAssert_Impl( ("Header corruption, block size is too large")
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 138); } else { }
;
139 DASSERTMSG( header->order <= DMemGlobalState.totalAllocs, "Header corruption, block order out of range")if ( !(header->order <= DMemGlobalState.totalAllocs) ) {
DAssert_Impl( ("Header corruption, block order out of range"
), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 139); } else { }
;
140}
141
142static void DMem_VerifyTail(MemoryBlockTail * tail) {
143 DASSERTMSG( DMem_ClientCheckPtr(tail, sizeof(MemoryBlockTail)), "Tail corruption, invalid pointer")if ( !(DMem_ClientCheckPtr(tail, sizeof(MemoryBlockTail))) ) {
DAssert_Impl( ("Tail corruption, invalid pointer"), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 143); } else { }
;
144 DASSERTMSG( DMem_VerifyGuardArea(tail->guard), "Tail corruption, possible overwrite" )if ( !(DMem_VerifyGuardArea(tail->guard)) ) { DAssert_Impl
( ("Tail corruption, possible overwrite"), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 144); } else { }
;
145}
146
147static MemoryBlockHeader * DMem_VerifyBlock(void * memptr) {
148 MemoryBlockHeader * header;
149 MemoryBlockTail * tail;
150
151 /* check if the pointer is valid */
152 DASSERTMSG( DMem_ClientCheckPtr(memptr, 1), "Invalid pointer")if ( !(DMem_ClientCheckPtr(memptr, 1)) ) { DAssert_Impl( ("Invalid pointer"
), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 152); } else { }
;
153
154 /* check if the block header is valid */
155 header = (MemoryBlockHeader *)((byte_t *)memptr - sizeof(MemoryBlockHeader));
156 DMem_VerifyHeader(header);
157 /* check that the memory itself is valid */
158 DASSERTMSG( DMem_ClientCheckPtr(memptr, DMEM_MIN(MAX_CHECK_BYTES,header->size)), "Block memory invalid" )if ( !(DMem_ClientCheckPtr(memptr, (MAX_CHECK_BYTES) < (header
->size) ? (MAX_CHECK_BYTES) : (header->size))) ) { DAssert_Impl
( ("Block memory invalid"), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 158); } else { }
;
159 /* check that the pointer to the alloc list is valid */
160 DASSERTMSG( DMem_ClientCheckPtr(header->listEnter, sizeof(MemoryListLink)), "Header corruption, alloc list pointer invalid" )if ( !(DMem_ClientCheckPtr(header->listEnter, sizeof(MemoryListLink
))) ) { DAssert_Impl( ("Header corruption, alloc list pointer invalid"
), "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 160); } else { }
;
161 /* check the tail of the block for overruns */
162 tail = (MemoryBlockTail *) ( (byte_t *)memptr + header->size );
163 DMem_VerifyTail(tail);
164
165 return header;
166}
167
168static MemoryBlockHeader * DMem_GetHeader(void * memptr) {
169 MemoryBlockHeader * header = DMem_VerifyBlock(memptr);
170 return header;
171}
172
173/*
174 * Should be called before any other DMem_XXX function
175 */
176void DMem_Initialize() {
177 DMemMutex = DMutex_Create();
178 DMutex_Enter(DMemMutex);
179 DMemGlobalState.pfnAlloc = NULL((void*)0);
180 DMemGlobalState.pfnFree = NULL((void*)0);
181 DMemGlobalState.pfnCheckPtr = NULL((void*)0);
182 DMemGlobalState.biggestBlock = 0;
183 DMemGlobalState.maxHeap = INT_MAX2147483647;
184 DMemGlobalState.totalHeapUsed = 0;
185 DMemGlobalState.failNextAlloc = FALSE0;
186 DMemGlobalState.totalAllocs = 0;
187 DMutex_Exit(DMemMutex);
188}
189
190void DMem_Shutdown() {
191 DMutex_Destroy(DMemMutex);
192}
193/*
194 * Allocates a block of memory, reserving extra space at the start and end of the
195 * block to store debug info on where the block was allocated, it's size, and
196 * 'guard' areas to catch overwrite/underwrite bugs
197 */
198void * DMem_AllocateBlock(size_t size, const char * filename, int linenumber) {
199 MemoryBlockHeader * header;
200 MemoryBlockTail * tail;
201 size_t debugBlockSize;
202 byte_t * memptr = NULL((void*)0);
203
204 DMutex_Enter(DMemMutex);
205 if (DMemGlobalState.failNextAlloc) {
206 /* force an allocation failure if so ordered */
207 DMemGlobalState.failNextAlloc = FALSE0; /* reset flag */
208 goto Exit;
209 }
210
211 /* allocate a block large enough to hold extra debug info */
212 debugBlockSize = sizeof(MemoryBlockHeader) + size + sizeof(MemoryBlockTail);
213 header = (MemoryBlockHeader *)DMem_ClientAllocate(debugBlockSize);
214 if (header == NULL((void*)0)) {
215 goto Exit;
216 }
217
218 /* add block to list of allocated memory */
219 header->listEnter = DMem_TrackBlock(header);
220 if ( header->listEnter == NULL((void*)0) ) {
221 DMem_ClientFree(header);
222 goto Exit;
223 }
224
225 /* store size of requested block */
226 header->size = size;
227 /* update maximum block size */
228 DMemGlobalState.biggestBlock = DMEM_MAX(header->size, DMemGlobalState.biggestBlock)(header->size) > (DMemGlobalState.biggestBlock) ? (header
->size) : (DMemGlobalState.biggestBlock)
;
229 /* update used memory total */
230 DMemGlobalState.totalHeapUsed += header->size;
231 /* store filename and linenumber where allocation routine was called */
232 strncpy(header->filename, filename, FILENAME_MAX4096);
233 header->linenumber = linenumber;
234 /* store the order the block was allocated in */
235 header->order = DMemGlobalState.totalAllocs++;
236 /* initialize memory to a recognizable 'inited' value */
237 memptr = (byte_t *)header + sizeof(MemoryBlockHeader);
238 memset(memptr, ByteInited, size);
239 /* put guard area before block */
240 memset(header->guard, ByteGuard, MAX_GUARD_BYTES);
241 /* put guard area after block */
242 tail = (MemoryBlockTail *)(memptr + size);
243 memset(tail->guard, ByteGuard, MAX_GUARD_BYTES);
244
245Exit:
246 DMutex_Exit(DMemMutex);
247 return memptr;
248}
249
250/*
251 * Frees block of memory allocated with DMem_AllocateBlock
252 */
253void DMem_FreeBlock(void * memptr) {
254 MemoryBlockHeader * header;
255
256 DMutex_Enter(DMemMutex);
257 if ( memptr == NULL((void*)0)) {
258 goto Exit;
259 }
260
261 /* get the debug block header preceding the allocated memory */
262 header = DMem_GetHeader(memptr);
263 /* fill memory with recognizable 'freed' value */
264 memset(memptr, ByteFreed, header->size);
265 /* mark block as freed */
266 header->listEnter->freed = TRUE1;
267 /* update used memory total */
268 DMemGlobalState.totalHeapUsed -= header->size;
269Exit:
270 DMutex_Exit(DMemMutex);
271}
272
273static void DMem_DumpHeader(MemoryBlockHeader * header) {
274 char report[FILENAME_MAX4096+MAX_DECIMAL_DIGITS*3+1];
275 static const char * reportFormat =
276 "file: %s, line %d\n"
277 "size: %d bytes\n"
278 "order: %d\n"
279 "-------";
280
281 DMem_VerifyHeader(header);
6
Calling 'DMem_VerifyHeader'
282 sprintf(report, reportFormat, header->filename, header->linenumber, header->size, header->order)__builtin___sprintf_chk (report, 2 - 1, __builtin_object_size
(report, 2 > 1), reportFormat, header->filename, header
->linenumber, header->size, header->order)
;
283 DTRACE_PRINTLN(report){ static dtrace_id _dt_lineid_ = UNDEFINED_TRACE_ID; DTrace_PrintFunction
((DTrace_VPrintln), &_Dt_FileTraceId, &_dt_lineid_, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 283, (0), ((report)), (0), (0), (0), (0), (0), (0), (0), (0
) ); }
;
284}
285
286/*
287 * Call this function at shutdown time to report any leaked blocks
288 */
289void DMem_ReportLeaks() {
290 MemoryListLink * link;
291
292 DMutex_Enter(DMemMutex);
293
294 /* Force memory leaks to be output regardless of trace settings */
295 DTrace_EnableFile(__FILE__"/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c", TRUE1);
296 DTRACE_PRINTLN("--------------------------"){ static dtrace_id _dt_lineid_ = UNDEFINED_TRACE_ID; DTrace_PrintFunction
((DTrace_VPrintln), &_Dt_FileTraceId, &_dt_lineid_, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 296, (0), (("--------------------------")), (0), (0), (0), (
0), (0), (0), (0), (0) ); }
;
297 DTRACE_PRINTLN("Debug Memory Manager Leaks"){ static dtrace_id _dt_lineid_ = UNDEFINED_TRACE_ID; DTrace_PrintFunction
((DTrace_VPrintln), &_Dt_FileTraceId, &_dt_lineid_, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 297, (0), (("Debug Memory Manager Leaks")), (0), (0), (0), (
0), (0), (0), (0), (0) ); }
;
298 DTRACE_PRINTLN("--------------------------"){ static dtrace_id _dt_lineid_ = UNDEFINED_TRACE_ID; DTrace_PrintFunction
((DTrace_VPrintln), &_Dt_FileTraceId, &_dt_lineid_, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug/debug_mem.c"
, 298, (0), (("--------------------------")), (0), (0), (0), (
0), (0), (0), (0), (0) ); }
;
299
300 /* walk through allocated list and dump any blocks not marked as freed */
301 link = MemoryList.next;
302 while (link != NULL((void*)0)) {
1
Assuming 'link' is not equal to NULL
2
Loop condition is true. Entering loop body
303 if ( !link->freed ) {
3
Assuming field 'freed' is 0
4
Taking true branch
304 DMem_DumpHeader(link->header);
5
Calling 'DMem_DumpHeader'
305 }
306 link = link->next;
307 }
308
309 DMutex_Exit(DMemMutex);
310}
311
312void DMem_SetAllocCallback( DMEM_ALLOCFN pfn ) {
313 DMutex_Enter(DMemMutex);
314 DMemGlobalState.pfnAlloc = pfn;
315 DMutex_Exit(DMemMutex);
316}
317
318void DMem_SetFreeCallback( DMEM_FREEFN pfn ) {
319 DMutex_Enter(DMemMutex);
320 DMemGlobalState.pfnFree = pfn;
321 DMutex_Exit(DMemMutex);
322}
323
324void DMem_SetCheckPtrCallback( DMEM_CHECKPTRFN pfn ) {
325 DMutex_Enter(DMemMutex);
326 DMemGlobalState.pfnCheckPtr = pfn;
327 DMutex_Exit(DMemMutex);
328}
329
330void DMem_DisableMutex() {
331 DMemMutex = NULL((void*)0);
332}
333
334#endif /* defined(DEBUG) */
335
336/* The following line is only here to prevent compiler warnings
337 * on release (non-debug) builds
338 */
339static int dummyVariable = 0;