Bug Summary

File:d/tclobj.c
Warning:line 104, column 32
Using a fixed address is not portable because that address will probably not be valid in all environments or platforms

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 tclobj.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 tclobj.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/*
32 * tclobj.c --
33 *
34 * Helper routines for managing Tcl_Obj types.
35 */
36
37#include "nsd.h"
38
39/*
40 * Local functions defined in this file.
41 */
42
43static Tcl_UpdateStringProc UpdateStringOfAddr;
44static Tcl_SetFromAnyProc SetAddrFromAny;
45
46/*
47 * Local variables defined in this file.
48 */
49
50static const Tcl_ObjType addrType = {
51 "ns:addr",
52 NULL((void*)0),
53 NULL((void*)0),
54 UpdateStringOfAddr,
55 SetAddrFromAny
56};
57
58static const Tcl_ObjType *byteArrayTypePtr; /* For NsTclObjIsByteArray(). */
59static const Tcl_ObjType *properByteArrayTypePtr; /* For NsTclObjIsByteArray(). */
60
61/*
62 *----------------------------------------------------------------------
63 *
64 * NsTclInitAddrType --
65 *
66 * Initialize the Tcl address object type and cache the bytearray Tcl
67 * built-in type. Starting with Tcl 8.7a1, Tcl has actually two different
68 * types for bytearrays, the old "tclByteArrayType" and a new
69 * "properByteArrayType", where both have the string name "bytearray".
70 *
71 * Results:
72 * None.
73 *
74 * Side effects:
75 * None.
76 *
77 *----------------------------------------------------------------------
78 */
79
80void
81NsTclInitAddrType(void)
82{
83 Tcl_Obj *newByteObj;
84
85 Tcl_RegisterObjType(&addrType);
86 /*
87 * Get the "tclByteArrayType" via name "bytearray".
88 */
89 byteArrayTypePtr = Tcl_GetObjType("bytearray");
90
91 /*
92 * Get the "properByteArrayType" via a TclObj.
93 * In versions before Tcl 8.7, both values will be the same.
94 */
95 newByteObj = Tcl_NewByteArrayObj(NULL((void*)0), 0);
96 properByteArrayTypePtr = newByteObj->typePtr;
97 if (properByteArrayTypePtr == byteArrayTypePtr) {
1
Assuming 'properByteArrayTypePtr' is equal to 'byteArrayTypePtr'
2
Taking true branch
98 /*
99 * When both values are the same, we are in a Tcl version before 8.7,
100 * where we have no properByteArrayTypePtr. So set it to an invalid
101 * value to avoid potential confusions. Without this stunt, we would
102 * need several ifdefs.
103 */
104 properByteArrayTypePtr = (Tcl_ObjType *)INT2PTR(0xffffff)((void *)(intptr_t)(0xffffff));
3
Using a fixed address is not portable because that address will probably not be valid in all environments or platforms
105 }
106 Tcl_DecrRefCount(newByteObj)do { Tcl_Obj *_objPtr = (newByteObj); if (_objPtr->refCount
-- <= 1) { TclFreeObj(_objPtr); } } while(0)
;
107}
108
109
110/*
111 *----------------------------------------------------------------------
112 *
113 * Ns_TclResetObjType --
114 *
115 * Reset the given Tcl_Obj type, freeing any type specific
116 * internal representation. The new Tcl_Obj type might be NULL.
117 *
118 * Results:
119 * None.
120 *
121 * Side effects:
122 * Depends on object type.
123 *
124 *----------------------------------------------------------------------
125 */
126
127void
128Ns_TclResetObjType(Tcl_Obj *objPtr, const Tcl_ObjType *newTypePtr)
129{
130 const Tcl_ObjType *typePtr;
131
132 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
133
134 typePtr = objPtr->typePtr;
135 if (typePtr != NULL((void*)0) && typePtr->freeIntRepProc != NULL((void*)0)) {
136 (*typePtr->freeIntRepProc)(objPtr);
137 }
138 objPtr->typePtr = newTypePtr;
139}
140
141
142/*
143 *----------------------------------------------------------------------
144 *
145 * Ns_TclSetTwoPtrValue --
146 *
147 * Reset the given objects type and values, freeing any existing
148 * internal rep.
149 *
150 * Results:
151 * None.
152 *
153 * Side effects:
154 * Depends on object type.
155 *
156 *----------------------------------------------------------------------
157 */
158
159void
160Ns_TclSetTwoPtrValue(Tcl_Obj *objPtr, const Tcl_ObjType *newTypePtr,
161 void *ptr1, void *ptr2)
162{
163 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
164
165 Ns_TclResetObjType(objPtr, newTypePtr);
166 objPtr->internalRep.twoPtrValue.ptr1 = ptr1;
167 objPtr->internalRep.twoPtrValue.ptr2 = ptr2;
168}
169
170
171/*
172 *----------------------------------------------------------------------
173 *
174 * Ns_TclSetOtherValuePtr --
175 *
176 * Reset the given objects type and value, freeing any existing
177 * internal rep.
178 *
179 * Results:
180 * None.
181 *
182 * Side effects:
183 * Depends on object type.
184 *
185 *----------------------------------------------------------------------
186 */
187
188void
189Ns_TclSetOtherValuePtr(Tcl_Obj *objPtr, const Tcl_ObjType *newTypePtr, void *value)
190{
191 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
192 NS_NONNULL_ASSERT(newTypePtr != NULL)((void) (0));
193 NS_NONNULL_ASSERT(value != NULL)((void) (0));
194
195 Ns_TclResetObjType(objPtr, newTypePtr);
196 objPtr->internalRep.otherValuePtr = value;
197}
198
199
200/*
201 *----------------------------------------------------------------------
202 *
203 * Ns_TclSetStringRep --
204 *
205 * Copy length bytes and set objects string rep. The objects
206 * existing string rep *must* have already been freed. Tcl uses
207 * as well "int" and not "size" (internally and via interface)
208 *
209 * Results:
210 * None.
211 *
212 * Side effects:
213 * Memory is allocated.
214 *
215 *----------------------------------------------------------------------
216 */
217
218void
219Ns_TclSetStringRep(Tcl_Obj *objPtr, const char *bytes, int length)
220{
221 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
222 NS_NONNULL_ASSERT(bytes != NULL)((void) (0));
223
224 if (length < 1) {
225 length = (int)strlen(bytes);
226 }
227 objPtr->length = length;
228 objPtr->bytes = ckalloc((unsigned) length + 1u)((void *) Tcl_Alloc((unsigned)((unsigned) length + 1u)));
229 memcpy(objPtr->bytes, bytes, (size_t) length + 1u);
230}
231
232
233
234/*
235 *----------------------------------------------------------------------
236 *
237 * Ns_TclSetFromAnyError --
238 *
239 * This procedure is registered as the setFromAnyProc for an
240 * object type when it doesn't make sense to generate its internal
241 * form from the string representation alone.
242 *
243 * Results:
244 * The return value is always TCL_ERROR, and an error message is
245 * left in interp's result if interp isn't NULL.
246 *
247 * Side effects:
248 * None.
249 *
250 *----------------------------------------------------------------------
251 */
252
253int
254Ns_TclSetFromAnyError(Tcl_Interp *interp, Tcl_Obj *UNUSED(objPtr)UNUSED_objPtr __attribute__((__unused__)))
255{
256 Tcl_AppendToObj(Tcl_GetObjResult(interp),
257 "can't convert value to requested type except via prescribed API",
258 -1);
259 return TCL_ERROR1;
260}
261
262
263/*
264 *----------------------------------------------------------------------
265 *
266 * Ns_TclGetAddrFromObj --
267 *
268 * Return the internal pointer of an address Tcl_Obj.
269 *
270 * Results:
271 * TCL_OK or TCL_ERROR if conversion failed or not the correct type.
272 *
273 * Side effects:
274 * Object may be converted to address type.
275 *
276 *----------------------------------------------------------------------
277 */
278
279int
280Ns_TclGetAddrFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
281 const char *type, void **addrPtrPtr)
282{
283 int result = TCL_OK0;
284
285 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
286 NS_NONNULL_ASSERT(type != NULL)((void) (0));
287 NS_NONNULL_ASSERT(addrPtrPtr != NULL)((void) (0));
288
289 if (Tcl_ConvertToType(interp, objPtr, &addrType) != TCL_OK0) {
290 result = TCL_ERROR1;
291
292 } else if (objPtr->internalRep.twoPtrValue.ptr1 != (void *) type) {
293 Ns_TclPrintfResult(interp, "incorrect type: %s", Tcl_GetString(objPtr));
294 result = TCL_ERROR1;
295
296 } else {
297 *addrPtrPtr = objPtr->internalRep.twoPtrValue.ptr2;
298 }
299
300 return result;
301}
302
303
304/*
305 *----------------------------------------------------------------------
306 *
307 * Ns_TclSetAddrObj --
308 *
309 * Convert the given object to the ns:addr type.
310 *
311 * Results:
312 * None.
313 *
314 * Side effects:
315 * None.
316 *
317 *----------------------------------------------------------------------
318 */
319
320void
321Ns_TclSetAddrObj(Tcl_Obj *objPtr, const char *type, void *addr)
322{
323 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
324 NS_NONNULL_ASSERT(type != NULL)((void) (0));
325 NS_NONNULL_ASSERT(addr != NULL)((void) (0));
326
327 if (Tcl_IsShared(objPtr)((objPtr)->refCount > 1)) {
328 Tcl_Panic("Ns_TclSetAddrObj called with shared object");
329 }
330 Ns_TclSetTwoPtrValue(objPtr, &addrType, (void *) type, addr);
331 Tcl_InvalidateStringRep(objPtr);
332}
333
334
335/*
336 *----------------------------------------------------------------------
337 *
338 * Ns_TclGetOpaqueFromObj --
339 *
340 * Get the internal pointer of an address Tcl_Obj.
341 *
342 * Results:
343 * TCL_OK or TCL_ERROR if object was not of the ns:addr type.
344 *
345 * Side effects:
346 * None.
347 *
348 *----------------------------------------------------------------------
349 */
350
351int
352Ns_TclGetOpaqueFromObj(const Tcl_Obj *objPtr, const char *type, void **addrPtrPtr)
353{
354 int result = TCL_OK0;
355
356 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
357 NS_NONNULL_ASSERT(type != NULL)((void) (0));
358 NS_NONNULL_ASSERT(addrPtrPtr != NULL)((void) (0));
359
360 if (objPtr->typePtr == &addrType
361 && objPtr->internalRep.twoPtrValue.ptr1 == (void *) type) {
362 *addrPtrPtr = objPtr->internalRep.twoPtrValue.ptr2;
363 } else {
364 char s[33] = {0};
365 uintptr_t t = 0u, a = 0u;
366
367 if ((sscanf(Tcl_GetString((Tcl_Obj *) objPtr), "t%20" SCNxPTR"l" "x" "-a%20" SCNxPTR"l" "x" "-%32s", &t, &a, s) != 3)
368 || (strcmp(s, type) != 0)
369 || (t != (uintptr_t)type)
370 ) {
371 result = TCL_ERROR1;
372 } else {
373 *addrPtrPtr = (void *)a;
374 }
375 }
376
377 return result;
378}
379
380
381/*
382 *----------------------------------------------------------------------
383 *
384 * Ns_TclSetOpaqueObj --
385 *
386 * Convert the given object to the ns:addr type without
387 * invalidating the current string rep. It is OK if the object
388 * is shared.
389 *
390 * Results:
391 * None.
392 *
393 * Side effects:
394 * None.
395 *
396 *----------------------------------------------------------------------
397 */
398
399void
400Ns_TclSetOpaqueObj(Tcl_Obj *objPtr, const char *type, void *addr)
401{
402 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
403 NS_NONNULL_ASSERT(type != NULL)((void) (0));
404
405 Ns_TclSetTwoPtrValue(objPtr, &addrType, (void *) type, addr);
406}
407
408
409/*
410 *----------------------------------------------------------------------
411 *
412 * NsTclObjIsByteArray --
413 *
414 * Does the given Tcl_Obj have a byte array internal rep? The
415 * function determines when it is safe to interpret a string as a
416 * byte array directly.
417 *
418 * Results:
419 * Boolean.
420 *
421 * Side effects:
422 * None.
423 *
424 *----------------------------------------------------------------------
425 */
426
427bool_Bool
428NsTclObjIsByteArray(const Tcl_Obj *objPtr)
429{
430 bool_Bool result;
431
432 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
433
434 /*
435 * This function resembles the tclInt.h function for testing pure byte
436 * arrays. In versions up to at least on Tcl 8.6, a pure byte array was
437 * defined as a byte array without a string rep. Starting with Tcl
438 * 8.7a1, Tcl has introduced the properByteArrayTypePtr, which allows as
439 * well a string rep.
440 */
441#ifdef NS_TCL_PRE87
442 result = ((objPtr->typePtr == byteArrayTypePtr) && (objPtr->bytes == NULL((void*)0)));
443#else
444 result = (objPtr->typePtr == properByteArrayTypePtr);
445#endif
446
447#if 0
448 fprintf(stderr, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n",__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n"
, (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr
== properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr
), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0
) ? "string" : objPtr->typePtr->name, result)
449 (void*)objPtr,__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n"
, (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr
== properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr
), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0
) ? "string" : objPtr->typePtr->name, result)
450 (void*)(objPtr->typePtr),__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n"
, (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr
== properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr
), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0
) ? "string" : objPtr->typePtr->name, result)
451 (objPtr->typePtr == properByteArrayTypePtr),__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n"
, (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr
== properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr
), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0
) ? "string" : objPtr->typePtr->name, result)
452 (objPtr->typePtr == byteArrayTypePtr),__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n"
, (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr
== properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr
), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0
) ? "string" : objPtr->typePtr->name, result)
453 (void*)(objPtr->bytes),__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n"
, (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr
== properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr
), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0
) ? "string" : objPtr->typePtr->name, result)
454 objPtr->typePtr == NULL ? "string" : objPtr->typePtr->name,__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n"
, (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr
== properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr
), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0
) ? "string" : objPtr->typePtr->name, result)
455 result)__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n"
, (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr
== properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr
), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0
) ? "string" : objPtr->typePtr->name, result)
;
456#endif
457
458 return result;
459}
460
461
462/*
463 *----------------------------------------------------------------------
464 *
465 * NsTclObjIsEncodedByteArray --
466 *
467 * This function is true, when we encounter a bytearray with a string
468 * rep. In this cases, it is necessary to use Tcl_UtfToExternalDString()
469 * to obtain the proper byte array.
470 *
471 * Results:
472 * Boolean.
473 *
474 * Side effects:
475 * None.
476 *
477 *----------------------------------------------------------------------
478 */
479
480bool_Bool
481NsTclObjIsEncodedByteArray(const Tcl_Obj *objPtr)
482{
483 NS_NONNULL_ASSERT(objPtr != NULL)((void) (0));
484
485 return ((objPtr->typePtr == byteArrayTypePtr) && (objPtr->bytes != NULL((void*)0)));
486}
487
488
489/*
490 *----------------------------------------------------------------------
491 *
492 * UpdateStringOfAddr --
493 *
494 * Update the string representation for an address object.
495 * Note: This procedure does not free an existing old string rep
496 * so storage will be lost if this has not already been done.
497 *
498 * Results:
499 * None.
500 *
501 * Side effects:
502 * None.
503 *
504 *----------------------------------------------------------------------
505 */
506
507static void
508UpdateStringOfAddr(Tcl_Obj *objPtr)
509{
510 const char *type = objPtr->internalRep.twoPtrValue.ptr1;
511 const void *addr = objPtr->internalRep.twoPtrValue.ptr2;
512 char buf[128];
513 int len;
514
515 len = snprintf(buf, sizeof(buf), "t%" PRIxPTR "-a%" PRIxPTR "-%s", (uintptr_t)type, (uintptr_t)addr, type)__builtin___snprintf_chk (buf, sizeof(buf), 2 - 1, __builtin_object_size
(buf, 2 > 1), "t%" "l" "x" "-a%" "l" "x" "-%s", (uintptr_t
)type, (uintptr_t)addr, type)
;
516 Ns_TclSetStringRep(objPtr, buf, len);
517}
518
519
520/*
521 *----------------------------------------------------------------------
522 *
523 * SetAddrFromAny --
524 *
525 * Attempt to generate an address internal form for the Tcl_Obj.
526 *
527 * Results:
528 * The return value is a standard Tcl result. If an error occurs
529 * during conversion, an error message is left in the interpreter's
530 * result unless interp is NULL.
531 *
532 * Side effects:
533 * None.
534 *
535 *----------------------------------------------------------------------
536 */
537
538static int
539SetAddrFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr)
540{
541 int result = TCL_OK0;
542 void *type, *addr;
543 char *chars;
544
545 chars = Tcl_GetString(objPtr);
546 if ((sscanf(chars, "t%20p-a%20p", &type, &addr) != 2)
547 || (type == NULL((void*)0))
548 || (addr == NULL((void*)0))
549 ) {
550 Ns_TclPrintfResult(interp, "invalid address \"%s\"", chars);
551 result = TCL_ERROR1;
552 } else {
553 Ns_TclSetTwoPtrValue(objPtr, &addrType, type, addr);
554 }
555
556 return result;
557}
558
559
560/*
561 * Local Variables:
562 * mode: c
563 * c-basic-offset: 4
564 * fill-column: 78
565 * indent-tabs-mode: nil
566 * End:
567 */