Bug Summary

File:jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c
Warning:line 271, column 16
Access to field 'packet' results in a dereference of a null pointer (loaded from variable 'pL')

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 debugLoop.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 JDWP_LOGGING -I /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/unix/native/libjdwp -I /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/jdk.jdwp.agent -I /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/include -I /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/export -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 -O2 -Wno-unused-parameter -Wno-unused -Wno-unused-function -std=c99 -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -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/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c
1/*
2 * Copyright (c) 1998, 2020, 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#include "util.h"
27#include "transport.h"
28#include "debugLoop.h"
29#include "debugDispatch.h"
30#include "standardHandlers.h"
31#include "inStream.h"
32#include "outStream.h"
33#include "threadControl.h"
34
35
36static void JNICALL reader(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);
37static void enqueue(jdwpPacket *p);
38static jboolean dequeue(jdwpPacket *p);
39static void notifyTransportError(void);
40
41struct PacketList {
42 jdwpPacket packet;
43 struct PacketList *next;
44};
45
46static volatile struct PacketList *cmdQueue;
47static jrawMonitorID cmdQueueLock;
48static jrawMonitorID vmDeathLock;
49static jboolean transportError;
50
51static jboolean
52lastCommand(jdwpCmdPacket *cmd)
53{
54 if ((cmd->cmdSet == JDWP_COMMAND_SET(VirtualMachine)1) &&
55 ((cmd->cmd == JDWP_COMMAND(VirtualMachine, Dispose)6) ||
56 (cmd->cmd == JDWP_COMMAND(VirtualMachine, Exit)10))) {
57 return JNI_TRUE1;
58 } else {
59 return JNI_FALSE0;
60 }
61}
62
63void
64debugLoop_initialize(void)
65{
66 vmDeathLock = debugMonitorCreate("JDWP VM_DEATH Lock");
67}
68
69void
70debugLoop_sync(void)
71{
72 debugMonitorEnter(vmDeathLock);
73 debugMonitorExit(vmDeathLock);
74}
75
76/*
77 * This is where all the work gets done.
78 */
79
80void
81debugLoop_run(void)
82{
83 jboolean shouldListen;
84 jdwpPacket p;
85 jvmtiStartFunction func;
86
87 /* Initialize all statics */
88 /* We may be starting a new connection after an error */
89 cmdQueue = NULL((void*)0);
90 cmdQueueLock = debugMonitorCreate("JDWP Command Queue Lock");
91 transportError = JNI_FALSE0;
92
93 shouldListen = JNI_TRUE1;
94
95 func = &reader;
96 (void)spawnNewThread(func, NULL((void*)0), "JDWP Command Reader");
97
98 standardHandlers_onConnect();
99 threadControl_onConnect();
100
101 /* Okay, start reading cmds! */
102 while (shouldListen) {
103 if (!dequeue(&p)) {
104 break;
105 }
106
107 if (p.type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
108 /*
109 * Its a reply packet.
110 */
111 continue;
112 } else {
113 /*
114 * Its a cmd packet.
115 */
116 jdwpCmdPacket *cmd = &p.type.cmd;
117 PacketInputStream in;
118 PacketOutputStream out;
119 CommandHandler func;
120 const char *cmdSetName;
121 const char *cmdName;
122
123 /* Should reply be sent to sender.
124 * For error handling, assume yes, since
125 * only VM/exit does not reply
126 */
127 jboolean replyToSender = JNI_TRUE1;
128
129 /*
130 * For all commands we hold the vmDeathLock
131 * while executing and replying to the command. This ensures
132 * that a command after VM_DEATH will be allowed to complete
133 * before the thread posting the VM_DEATH continues VM
134 * termination.
135 */
136 debugMonitorEnter(vmDeathLock);
137
138 /* Initialize the input and output streams */
139 inStream_init(&in, p);
140 outStream_initReply(&out, inStream_id(&in));
141
142 func = debugDispatch_getHandler(cmd->cmdSet, cmd->cmd, &cmdSetName, &cmdName);
143 LOG_MISC(("Command set %s(%d), command %s(%d)",((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
,144), log_message_end ("Command set %s(%d), command %s(%d)",
cmdSetName, cmd->cmdSet, cmdName, cmd->cmd)):((void)0)
)
144 cmdSetName, cmd->cmdSet, cmdName, cmd->cmd))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
,144), log_message_end ("Command set %s(%d), command %s(%d)",
cmdSetName, cmd->cmdSet, cmdName, cmd->cmd)):((void)0)
)
;
145 if (func == NULL((void*)0)) {
146 /* we've never heard of this, so I guess we
147 * haven't implemented it.
148 * Handle gracefully for future expansion
149 * and platform / vendor expansion.
150 */
151 outStream_setError(&out, JDWP_ERROR(NOT_IMPLEMENTED)99);
152 } else if (gdata->vmDead &&
153 ((cmd->cmdSet) != JDWP_COMMAND_SET(VirtualMachine)1)) {
154 /* Protect the VM from calls while dead.
155 * VirtualMachine cmdSet quietly ignores some cmds
156 * after VM death, so, it sends it's own errors.
157 */
158 outStream_setError(&out, JDWP_ERROR(VM_DEAD)112);
159 } else {
160 /* Call the command handler */
161 replyToSender = func(&in, &out);
162 }
163
164 /* Reply to the sender */
165 if (replyToSender) {
166 if (inStream_error(&in)) {
167 outStream_setError(&out, inStream_error(&in));
168 }
169 outStream_sendReply(&out);
170 }
171
172 /*
173 * Release the vmDeathLock as the reply has been posted.
174 */
175 debugMonitorExit(vmDeathLock);
176
177 inStream_destroy(&in);
178 outStream_destroy(&out);
179
180 shouldListen = !lastCommand(cmd);
181 }
182 }
183 threadControl_onDisconnect();
184 standardHandlers_onDisconnect();
185
186 /*
187 * Cut off the transport immediately. This has the effect of
188 * cutting off any events that the eventHelper thread might
189 * be trying to send.
190 */
191 transport_close();
192 debugMonitorDestroy(cmdQueueLock);
193
194 /* Reset for a new connection to this VM if it's still alive */
195 if ( ! gdata->vmDead ) {
196 debugInit_reset(getEnv());
197 }
198}
199
200/* Command reader */
201static void JNICALL
202reader(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg)
203{
204 jdwpPacket packet;
205 jdwpCmdPacket *cmd;
206 jboolean shouldListen = JNI_TRUE1;
207
208 LOG_MISC(("Begin reader thread"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
,208), log_message_end ("Begin reader thread")):((void)0))
;
1
Assuming the condition is false
2
'?' condition is false
209
210 while (shouldListen) {
3
Loop condition is true. Entering loop body
211 jint rc;
212
213 rc = transport_receivePacket(&packet);
214
215 /* I/O error or EOF */
216 if (rc != 0 || (rc
4.1
'rc' is equal to 0
== 0 && packet.type.cmd.len == 0)) {
4
Assuming 'rc' is equal to 0
5
Assuming field 'len' is not equal to 0
6
Taking false branch
217 shouldListen = JNI_FALSE0;
218 notifyTransportError();
219 } else if (packet.type.cmd.flags != JDWPTRANSPORT_FLAGS_NONE) {
7
Assuming field 'flags' is equal to JDWPTRANSPORT_FLAGS_NONE
8
Taking false branch
220 /*
221 * Close the connection when we get a jdwpCmdPacket with an
222 * invalid flags field value. This is a protocol violation
223 * so we drop the connection. Also this could be a web
224 * browser generating an HTTP request that passes the JDWP
225 * handshake. HTTP requests requires that everything be in
226 * the ASCII printable range so a flags value of
227 * JDWPTRANSPORT_FLAGS_NONE(0) cannot be generated via HTTP.
228 */
229 ERROR_MESSAGE(("Received jdwpPacket with flags != 0x%d (actual=0x%x) when a jdwpCmdPacket was expected.",( ((gdata->log_flags & (0x00000080))?(log_message_begin
("ERROR","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
,230), log_message_end ("Received jdwpPacket with flags != 0x%d (actual=0x%x) when a jdwpCmdPacket was expected."
, JDWPTRANSPORT_FLAGS_NONE, packet.type.cmd.flags)):((void)0)
), error_message ("Received jdwpPacket with flags != 0x%d (actual=0x%x) when a jdwpCmdPacket was expected."
, JDWPTRANSPORT_FLAGS_NONE, packet.type.cmd.flags) )
230 JDWPTRANSPORT_FLAGS_NONE, packet.type.cmd.flags))( ((gdata->log_flags & (0x00000080))?(log_message_begin
("ERROR","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
,230), log_message_end ("Received jdwpPacket with flags != 0x%d (actual=0x%x) when a jdwpCmdPacket was expected."
, JDWPTRANSPORT_FLAGS_NONE, packet.type.cmd.flags)):((void)0)
), error_message ("Received jdwpPacket with flags != 0x%d (actual=0x%x) when a jdwpCmdPacket was expected."
, JDWPTRANSPORT_FLAGS_NONE, packet.type.cmd.flags) )
;
231 shouldListen = JNI_FALSE0;
232 notifyTransportError();
233 } else {
234 const char *cmdSetName;
235 const char *cmdName;
236 cmd = &packet.type.cmd;
237
238 debugDispatch_getHandler(cmd->cmdSet, cmd->cmd, &cmdSetName, &cmdName);
239 LOG_MISC(("Command set %s(%d), command %s(%d)",((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
,240), log_message_end ("Command set %s(%d), command %s(%d)",
cmdSetName, cmd->cmdSet, cmdName, cmd->cmd)):((void)0)
)
9
Assuming the condition is false
10
'?' condition is false
240 cmdSetName, cmd->cmdSet, cmdName, cmd->cmd))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
,240), log_message_end ("Command set %s(%d), command %s(%d)",
cmdSetName, cmd->cmdSet, cmdName, cmd->cmd)):((void)0)
)
;
241
242 /*
243 * FIXME! We need to deal with high priority
244 * packets and queue flushes!
245 */
246 enqueue(&packet);
11
Calling 'enqueue'
247
248 shouldListen = !lastCommand(cmd);
249 }
250 }
251 LOG_MISC(("End reader thread"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
,251), log_message_end ("End reader thread")):((void)0))
;
252}
253
254/*
255 * The current system for queueing packets is highly
256 * inefficient, and should be rewritten! It'd be nice
257 * to avoid any additional memory allocations.
258 */
259
260static void
261enqueue(jdwpPacket *packet)
262{
263 struct PacketList *pL;
264 struct PacketList *walker;
265
266 pL = jvmtiAllocate((jint)sizeof(struct PacketList));
12
Value assigned to 'pL'
267 if (pL == NULL((void*)0)) {
13
Assuming 'pL' is equal to NULL
14
Taking true branch
268 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"packet list"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+8))), ((jvmtiError)(JVMTI_ERROR_MAX+64+8)), ("packet list"==
((void*)0)?"":"packet list"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c"
, 268); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+8)), "packet list"); }
;
15
'?' condition is false
269 }
270
271 pL->packet = *packet;
16
Access to field 'packet' results in a dereference of a null pointer (loaded from variable 'pL')
272 pL->next = NULL((void*)0);
273
274 debugMonitorEnter(cmdQueueLock);
275
276 if (cmdQueue == NULL((void*)0)) {
277 cmdQueue = pL;
278 debugMonitorNotify(cmdQueueLock);
279 } else {
280 walker = (struct PacketList *)cmdQueue;
281 while (walker->next != NULL((void*)0))
282 walker = walker->next;
283
284 walker->next = pL;
285 }
286
287 debugMonitorExit(cmdQueueLock);
288}
289
290static jboolean
291dequeue(jdwpPacket *packet) {
292 struct PacketList *node = NULL((void*)0);
293
294 debugMonitorEnter(cmdQueueLock);
295
296 while (!transportError && (cmdQueue == NULL((void*)0))) {
297 debugMonitorWait(cmdQueueLock);
298 }
299
300 if (cmdQueue != NULL((void*)0)) {
301 node = (struct PacketList *)cmdQueue;
302 cmdQueue = node->next;
303 }
304 debugMonitorExit(cmdQueueLock);
305
306 if (node != NULL((void*)0)) {
307 *packet = node->packet;
308 jvmtiDeallocate(node);
309 }
310 return (node != NULL((void*)0));
311}
312
313static void
314notifyTransportError(void) {
315 debugMonitorEnter(cmdQueueLock);
316 transportError = JNI_TRUE1;
317 debugMonitorNotify(cmdQueueLock);
318 debugMonitorExit(cmdQueueLock);
319}