Bug Summary

File:d/proc.c
Warning:line 137, column 43
The code calls sizeof() on a pointer type. This can produce an unexpected result

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name proc.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 -fhalf-no-semantic-interposition -mframe-pointer=none -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=/home/isvv/naviserver/nsd -resource-dir /usr/local/lib/clang/15.0.0 -D _FORTIFY_SOURCE=2 -D NDEBUG -D SYSTEM_MALLOC -I ../include -I /usr/include/tcl8.6 -D HAVE_CONFIG_H -internal-isystem /usr/local/lib/clang/15.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c99 -fdebug-compilation-dir=/home/isvv/naviserver/nsd -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker alpha -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-07-23-130959-11103-1 -x c proc.c
1/*
2 * The contents of this file are subject to the Mozilla Public License
3 * Version 1.1 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://mozilla.org/.
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 * the License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Original Code is AOLserver Code and related documentation
13 * distributed by AOL.
14 *
15 * The Initial Developer of the Original Code is America Online,
16 * Inc. Portions created by AOL are Copyright (C) 1999 America Online,
17 * Inc. All Rights Reserved.
18 *
19 * Alternatively, the contents of this file may be used under the terms
20 * of the GNU General Public License (the "GPL"), in which case the
21 * provisions of GPL are applicable instead of those above. If you wish
22 * to allow use of your version of this file only under the terms of the
23 * GPL and not to allow others to use your version of this file under the
24 * License, indicate your decision by deleting the provisions above and
25 * replace them with the notice and other provisions required by the GPL.
26 * If you do not delete the provisions above, a recipient may use your
27 * version of this file under either the License or the GPL.
28 */
29
30/*
31 * proc.c --
32 *
33 * Support for describing procs and their arguments (thread routines,
34 * callbacks, scheduled procs, etc.).
35 */
36
37#include "nsd.h"
38
39/*
40 * The following struct maintains callback and description for
41 * Ns_GetProcInfo.
42 */
43
44typedef struct Info {
45 Ns_ArgProc *proc;
46 const char *desc;
47} Info;
48
49/*
50 * Static functions defined in this file.
51 */
52
53static Ns_ArgProc ServerArgProc;
54static void AppendAddr(Tcl_DString *dsPtr, const char *prefix, const void *addr)
55 NS_GNUC_NONNULL(1)__attribute__((__nonnull__(1))) NS_GNUC_NONNULL(2)__attribute__((__nonnull__(2)));
56
57static Tcl_HashKeyProc FuncptrKey;
58static Tcl_CompareHashKeysProc CompareFuncptrKeys;
59static Tcl_AllocHashEntryProc AllocFuncptrEntry;
60static Tcl_FreeHashEntryProc FreeFuncptrEntry;
61
62/*
63 * Static variables defined in this file.
64 */
65
66static const Tcl_HashKeyType funPtrHashKeyType = {
67 1, /* version */
68 0, /* flags */
69 FuncptrKey, /* hashKeyProc */
70 CompareFuncptrKeys, /* compareKeysProc */
71 AllocFuncptrEntry, /* allocEntryProc */
72 FreeFuncptrEntry /* freeEntryProc */
73};
74
75typedef struct funcptrEntry_t {
76 ns_funcptr_t funcptr;
77} funcptrEntry_t;
78
79static Tcl_HashTable infoHashTable;
80
81static const struct proc {
82 ns_funcptr_t procAddr;
83 const char *desc;
84 Ns_ArgProc *argProc;
85} procs[] = {
86 { (ns_funcptr_t)NsTclThread, "ns:tclthread", NsTclThreadArgProc},
87 { (ns_funcptr_t)Ns_TclCallbackProc, "ns:tclcallback", Ns_TclCallbackArgProc},
88 { (ns_funcptr_t)NsTclConnLocation, "ns:tclconnlocation", Ns_TclCallbackArgProc},
89 { (ns_funcptr_t)NsTclSchedProc, "ns:tclschedproc", Ns_TclCallbackArgProc},
90 { (ns_funcptr_t)NsTclServerRoot, "ns:tclserverroot", Ns_TclCallbackArgProc},
91 { (ns_funcptr_t)NsTclSockProc, "ns:tclsockcallback", NsTclSockArgProc},
92 { (ns_funcptr_t)NsConnThread, "ns:connthread", NsConnArgProc},
93 { (ns_funcptr_t)NsTclFilterProc, "ns:tclfilter", Ns_TclCallbackArgProc},
94 { (ns_funcptr_t)NsShortcutFilterProc, "ns:shortcutfilter", NULL((void*)0)},
95 { (ns_funcptr_t)NsTclRequestProc, "ns:tclrequest", Ns_TclCallbackArgProc},
96 { (ns_funcptr_t)NsAdpPageProc, "ns:adppage", NsAdpPageArgProc},
97 { (ns_funcptr_t)Ns_FastPathProc, "ns:fastget", NULL((void*)0)},
98 { (ns_funcptr_t)NsTclTraceProc, "ns:tcltrace", Ns_TclCallbackArgProc},
99 { (ns_funcptr_t)NsTclUrl2FileProc, "ns:tclurl2file", Ns_TclCallbackArgProc},
100 { (ns_funcptr_t)NsMountUrl2FileProc, "ns:mounturl2file", NsMountUrl2FileArgProc},
101 { (ns_funcptr_t)Ns_FastUrl2FileProc, "ns:fasturl2file", ServerArgProc},
102 {NULL((void*)0), NULL((void*)0), NULL((void*)0)}
103};
104
105
106/*
107 *----------------------------------------------------------------------
108 *
109 * AllocFuncptrEntry --
110 *
111 * Allocate enough space for a Tcl_HashEntry including the payload. The
112 * function pointer is assigned to key.oneWordValue via memcpy().
113 *
114 * Results:
115 * Return a memory block casted to Tcl_HashEntry*.
116 *
117 * Side effects:
118 * Memory allocation.
119 *----------------------------------------------------------------------
120 */
121
122static Tcl_HashEntry *
123AllocFuncptrEntry(Tcl_HashTable *UNUSED(tablePtr)UNUSED_tablePtr __attribute__((__unused__)), void *keyPtr) {
124 Tcl_HashEntry *hPtr;
125 ns_funcptr_t value = ((funcptrEntry_t *)keyPtr)->funcptr;
126
127 /*
128 * The size of the function pointer might be larger than the data pointer.
129 * since we store the value starting with the oneWordValue, we have to
130 * allocate on some architectures a more than the Tcl_HashEntry, namely the
131 * differences of the sizes of these pointer types.
132 */
133 hPtr = (Tcl_HashEntry *)ns_malloc(sizeof(Tcl_HashEntry) +
134 MAX(sizeof(ns_funcptr_t), sizeof(char*))(((sizeof(ns_funcptr_t))>(sizeof(char*)))?(sizeof(ns_funcptr_t
)):(sizeof(char*)))
- sizeof(char*));
135 hPtr->clientData = NULL((void*)0);
136
137 memcpy(&hPtr->key.oneWordValue, &value, sizeof(value));
The code calls sizeof() on a pointer type. This can produce an unexpected result
138
139 return hPtr;
140}
141
142/*
143 *----------------------------------------------------------------------
144 *
145 * FreeFuncptrEntry --
146 *
147 * Free an entry in the funcptr hash table. The inverse operation of
148 * AllocFuncptrEntry().
149 *
150 * Results:
151 * None.
152 *
153 * Side effects:
154 * Free memory.
155 *----------------------------------------------------------------------
156 */
157static void
158FreeFuncptrEntry(Tcl_HashEntry *hPtr)
159{
160 ns_free(hPtr);
161}
162
163/*
164 *----------------------------------------------------------------------
165 *
166 * FuncptrKey --
167 *
168 * Compute an unsigned int hash value from a function pointer.
169 *
170 * Results:
171 * Returns the computed hash.
172 *
173 * Side effects:
174 * None.
175 *
176 *----------------------------------------------------------------------
177 */
178
179static unsigned int
180FuncptrKey(Tcl_HashTable *UNUSED(tablePtr)UNUSED_tablePtr __attribute__((__unused__)), void *keyPtr)
181{
182 /*
183 * Simply return the value part of the funcptrEntry as hash value.
184 */
185 return PTR2UINT(((funcptrEntry_t *)keyPtr)->funcptr)((unsigned int)(uintptr_t)(((funcptrEntry_t *)keyPtr)->funcptr
))
;
186}
187
188/*
189 *----------------------------------------------------------------------
190 *
191 * CompareFuncptrKeys --
192 *
193 * Compare two function pointers.
194 *
195 * Results:
196 * The return value is 0 if they are different and 1 if they are the
197 * same.
198 *
199 * Side effects:
200 * None.
201 *
202 *----------------------------------------------------------------------
203 */
204static int
205CompareFuncptrKeys(void *keyPtr, Tcl_HashEntry *hPtr)
206{
207 ns_funcptr_t funcptr;
208
209 memcpy(&funcptr, &hPtr->key.oneWordValue, sizeof(ns_funcptr_t));
210
211 return ((funcptrEntry_t *)keyPtr)->funcptr == funcptr;
212}
213
214
215/*
216 *----------------------------------------------------------------------
217 *
218 * NsInitProcInfo --
219 *
220 * Initialize the proc info API and default compiled-in callbacks.
221 *
222 * Results:
223 * None.
224 *
225 * Side effects:
226 * None.
227 *
228 *----------------------------------------------------------------------
229 */
230
231void
232NsInitProcInfo(void)
233{
234 const struct proc *procPtr;
235
236 Tcl_InitCustomHashTable(&infoHashTable, TCL_CUSTOM_PTR_KEYS(-1), &funPtrHashKeyType);
237 procPtr = procs;
238 while (procPtr->procAddr != NULL((void*)0)) {
239 Ns_RegisterProcInfo(procPtr->procAddr, procPtr->desc,
240 procPtr->argProc);
241 ++procPtr;
242 }
243}
244
245
246/*
247 *----------------------------------------------------------------------
248 *
249 * Ns_RegisterProcInfo --
250 *
251 * Register a proc description and a callback to describe the
252 * arguments e.g., a thread start arg.
253 *
254 * Results:
255 * None.
256 *
257 * Side effects:
258 * Given argProc will be invoked for given procAddr by
259 * Ns_GetProcInfo.
260 *
261 *----------------------------------------------------------------------
262 */
263
264void
265Ns_RegisterProcInfo(ns_funcptr_t procAddr, const char *desc, Ns_ArgProc *argProc)
266{
267 Tcl_HashEntry *hPtr;
268 Info *infoPtr;
269 int isNew;
270 funcptrEntry_t entry;
271
272 NS_NONNULL_ASSERT(procAddr != NULL)((void) (0));
273 NS_NONNULL_ASSERT(desc != NULL)((void) (0));
274
275 entry.funcptr = procAddr;
276 hPtr = Tcl_CreateHashEntry(&infoHashTable, (const char *)&entry, &isNew)(*((&infoHashTable)->createProc))(&infoHashTable, (
const char *)((const char *)&entry), &isNew)
;
277
278 if (isNew == 0) {
279 infoPtr = Tcl_GetHashValue(hPtr)((hPtr)->clientData);
280 } else {
281 infoPtr = ns_malloc(sizeof(Info));
282 Tcl_SetHashValue(hPtr, infoPtr)((hPtr)->clientData = (ClientData) (infoPtr));
283 }
284 infoPtr->desc = desc;
285 infoPtr->proc = argProc;
286}
287
288
289/*
290 *----------------------------------------------------------------------
291 *
292 * Ns_GetProcInfo --
293 *
294 * Format a string of information for the given proc
295 * and arg, invoking the argProc callback if it exists.
296 *
297 * Results:
298 * None.
299 *
300 * Side effects:
301 * String will be appended to given dsPtr.
302 *
303 *----------------------------------------------------------------------
304 */
305
306void
307Ns_GetProcInfo(Tcl_DString *dsPtr, ns_funcptr_t procAddr, const void *arg)
308{
309 const Tcl_HashEntry *hPtr;
310 const Info *infoPtr;
311 static const Info nullInfo = {NULL((void*)0), NULL((void*)0)};
312 funcptrEntry_t entry;
313
314 NS_NONNULL_ASSERT(dsPtr != NULL)((void) (0));
315
316 entry.funcptr = procAddr;
317 hPtr = Tcl_FindHashEntry(&infoHashTable, (const char *)&entry)(*((&infoHashTable)->findProc))(&infoHashTable, (const
char *)((const char *)&entry))
;
318
319 if (hPtr != NULL((void*)0)) {
320 infoPtr = Tcl_GetHashValue(hPtr)((hPtr)->clientData);
321 } else {
322 infoPtr = &nullInfo;
323 }
324 /* Ns_Log(Notice, "Ns_GetProcInfo: infoPtr->desc %p", infoPtr->desc);*/
325 if (infoPtr->desc != NULL((void*)0)) {
326 Tcl_DStringAppendElement(dsPtr, infoPtr->desc);
327 } else {
328 /*
329 * The following is a rather crude approach obtaining a hex print
330 * string from a function pointer. For our purposes, this should be
331 * good enough.
332 */
333 union {
334 ns_funcptr_t funcptr;
335 void *ptr;
336 } data;
337
338 data.funcptr = procAddr;
339 AppendAddr(dsPtr, "p", data.ptr);
340 }
341 /*Ns_Log(Notice, "Ns_GetProcInfo: infoPtr->proc %p", infoPtr->proc);*/
342 if (infoPtr->proc != NULL((void*)0)) {
343 (*infoPtr->proc)(dsPtr, arg);
344 } else {
345 AppendAddr(dsPtr, "a", arg);
346 }
347}
348
349
350/*
351 *----------------------------------------------------------------------
352 *
353 * Ns_StringArgProc --
354 *
355 * Info callback for procs which take a C string arg.
356 *
357 * Results:
358 * None.
359 *
360 * Side effects:
361 * None.
362 *
363 *----------------------------------------------------------------------
364 */
365
366void
367Ns_StringArgProc(Tcl_DString *dsPtr, const void *arg)
368{
369 const char *str = arg;
370
371 NS_NONNULL_ASSERT(dsPtr != NULL)((void) (0));
372
373 Tcl_DStringAppendElement(dsPtr, (str != NULL((void*)0)) ? str : NS_EMPTY_STRING);
374}
375
376
377/*
378 *----------------------------------------------------------------------
379 *
380 * ServerArgProc --
381 *
382 * Info callback for procs which take an NsServer arg.
383 *
384 * Results:
385 * None.
386 *
387 * Side effects:
388 * None.
389 *
390 *----------------------------------------------------------------------
391 */
392
393static void
394ServerArgProc(Tcl_DString *dsPtr, const void *arg)
395{
396 const NsServer *servPtr = arg;
397
398 Tcl_DStringAppendElement(dsPtr, (servPtr != NULL((void*)0)) ? servPtr->server : NS_EMPTY_STRING);
399}
400
401
402/*
403 *----------------------------------------------------------------------
404 *
405 * AppendAddr --
406 *
407 * Format a simple string with the given address.
408 *
409 * Results:
410 * None.
411 *
412 * Side effects:
413 * String will be appended to given dsPtr.
414 *
415 *----------------------------------------------------------------------
416 */
417
418static void
419AppendAddr(Tcl_DString *dsPtr, const char *prefix, const void *addr)
420{
421 NS_NONNULL_ASSERT(dsPtr != NULL)((void) (0));
422 NS_NONNULL_ASSERT(prefix != NULL)((void) (0));
423
424 Ns_DStringPrintf(dsPtr, " %s:%p", prefix, addr);
425}
426
427/*
428 * Local Variables:
429 * mode: c
430 * c-basic-offset: 4
431 * fill-column: 78
432 * indent-tabs-mode: nil
433 * End:
434 */