Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp
Warning:line 45, column 5
Value stored to 'count' is never read

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 Unified_cpp_xpcom_string0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/xpcom/string -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/xpcom/string -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/string -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/xpcom/string -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../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 -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-09-011502-17414-1 -x c++ Unified_cpp_xpcom_string0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "nsStringBuffer.h"
8
9#include "mozilla/MemoryReporting.h"
10#include "nsISupportsImpl.h"
11#include "nsString.h"
12
13void nsStringBuffer::AddRef() {
14 // Memory synchronization is not required when incrementing a
15 // reference count. The first increment of a reference count on a
16 // thread is not important, since the first use of the object on a
17 // thread can happen before it. What is important is the transfer
18 // of the pointer to that thread, which may happen prior to the
19 // first increment on that thread. The necessary memory
20 // synchronization is done by the mechanism that transfers the
21 // pointer between threads.
22#ifdef NS_BUILD_REFCNT_LOGGING1
23 uint32_t count =
24#endif
25 mRefCount.fetch_add(1, std::memory_order_relaxed)
26#ifdef NS_BUILD_REFCNT_LOGGING1
27 + 1
28#endif
29 ;
30 NS_LOG_ADDREF(this, count, "nsStringBuffer", sizeof(*this))NS_LogAddRef((this), (count), ("nsStringBuffer"), (uint32_t)(
sizeof(*this)))
;
31}
32
33void nsStringBuffer::Release() {
34 // Since this may be the last release on this thread, we need
35 // release semantics so that prior writes on this thread are visible
36 // to the thread that destroys the object when it reads mValue with
37 // acquire semantics.
38 uint32_t count = mRefCount.fetch_sub(1, std::memory_order_release) - 1;
39 NS_LOG_RELEASE(this, count, "nsStringBuffer")NS_LogRelease((this), (count), ("nsStringBuffer"));
40 if (count == 0) {
41 // We're going to destroy the object on this thread, so we need
42 // acquire semantics to synchronize with the memory released by
43 // the last release on other threads, that is, to ensure that
44 // writes prior to that release are now visible on this thread.
45 count = mRefCount.load(std::memory_order_acquire);
Value stored to 'count' is never read
46
47 free(this); // we were allocated with |malloc|
48 }
49}
50
51/**
52 * Alloc returns a pointer to a new string header with set capacity.
53 */
54already_AddRefed<nsStringBuffer> nsStringBuffer::Alloc(size_t aSize) {
55 NS_ASSERTION(aSize != 0, "zero capacity allocation not allowed")do { if (!(aSize != 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "zero capacity allocation not allowed"
, "aSize != 0", "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 55); MOZ_PretendNoReturn(); } } while (0)
;
56 NS_ASSERTION(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) &&do { if (!(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t
(-1)) && sizeof(nsStringBuffer) + aSize > aSize)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "mStorageSize will truncate"
, "sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && sizeof(nsStringBuffer) + aSize > aSize"
, "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 58); MOZ_PretendNoReturn(); } } while (0)
57 sizeof(nsStringBuffer) + aSize > aSize,do { if (!(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t
(-1)) && sizeof(nsStringBuffer) + aSize > aSize)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "mStorageSize will truncate"
, "sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && sizeof(nsStringBuffer) + aSize > aSize"
, "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 58); MOZ_PretendNoReturn(); } } while (0)
58 "mStorageSize will truncate")do { if (!(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t
(-1)) && sizeof(nsStringBuffer) + aSize > aSize)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "mStorageSize will truncate"
, "sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && sizeof(nsStringBuffer) + aSize > aSize"
, "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 58); MOZ_PretendNoReturn(); } } while (0)
;
59
60 auto* hdr = (nsStringBuffer*)malloc(sizeof(nsStringBuffer) + aSize);
61 if (hdr) {
62 hdr->mRefCount = 1;
63 hdr->mStorageSize = aSize;
64 NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr))NS_LogAddRef((hdr), (1), ("nsStringBuffer"), (uint32_t)(sizeof
(*hdr)))
;
65 }
66 return already_AddRefed(hdr);
67}
68
69template <typename CharT>
70static already_AddRefed<nsStringBuffer> DoCreate(const CharT* aData,
71 size_t aLength) {
72 RefPtr<nsStringBuffer> buffer =
73 nsStringBuffer::Alloc((aLength + 1) * sizeof(CharT));
74 if (MOZ_UNLIKELY(!buffer)(__builtin_expect(!!(!buffer), 0))) {
75 return nullptr;
76 }
77 auto* data = reinterpret_cast<CharT*>(buffer->Data());
78 memcpy(data, aData, aLength * sizeof(CharT));
79 data[aLength] = 0;
80 return buffer.forget();
81}
82
83already_AddRefed<nsStringBuffer> nsStringBuffer::Create(const char* aData,
84 size_t aLength) {
85 return DoCreate(aData, aLength);
86}
87
88already_AddRefed<nsStringBuffer> nsStringBuffer::Create(const char16_t* aData,
89 size_t aLength) {
90 return DoCreate(aData, aLength);
91}
92
93nsStringBuffer* nsStringBuffer::Realloc(nsStringBuffer* aHdr, size_t aSize) {
94 NS_ASSERTION(aSize != 0, "zero capacity allocation not allowed")do { if (!(aSize != 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "zero capacity allocation not allowed"
, "aSize != 0", "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 94); MOZ_PretendNoReturn(); } } while (0)
;
95 NS_ASSERTION(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) &&do { if (!(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t
(-1)) && sizeof(nsStringBuffer) + aSize > aSize)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "mStorageSize will truncate"
, "sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && sizeof(nsStringBuffer) + aSize > aSize"
, "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 97); MOZ_PretendNoReturn(); } } while (0)
96 sizeof(nsStringBuffer) + aSize > aSize,do { if (!(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t
(-1)) && sizeof(nsStringBuffer) + aSize > aSize)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "mStorageSize will truncate"
, "sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && sizeof(nsStringBuffer) + aSize > aSize"
, "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 97); MOZ_PretendNoReturn(); } } while (0)
97 "mStorageSize will truncate")do { if (!(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t
(-1)) && sizeof(nsStringBuffer) + aSize > aSize)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "mStorageSize will truncate"
, "sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && sizeof(nsStringBuffer) + aSize > aSize"
, "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 97); MOZ_PretendNoReturn(); } } while (0)
;
98
99 // no point in trying to save ourselves if we hit this assertion
100 NS_ASSERTION(!aHdr->IsReadonly(), "|Realloc| attempted on readonly string")do { if (!(!aHdr->IsReadonly())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "|Realloc| attempted on readonly string", "!aHdr->IsReadonly()"
, "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 100); MOZ_PretendNoReturn(); } } while (0)
;
101
102 // Treat this as a release and addref for refcounting purposes, since we
103 // just asserted that the refcount is 1. If we don't do that, refcount
104 // logging will claim we've leaked all sorts of stuff.
105 NS_LOG_RELEASE(aHdr, 0, "nsStringBuffer")NS_LogRelease((aHdr), (0), ("nsStringBuffer"));
106
107 aHdr = (nsStringBuffer*)realloc(aHdr, sizeof(nsStringBuffer) + aSize);
108 if (aHdr) {
109 NS_LOG_ADDREF(aHdr, 1, "nsStringBuffer", sizeof(*aHdr))NS_LogAddRef((aHdr), (1), ("nsStringBuffer"), (uint32_t)(sizeof
(*aHdr)))
;
110 aHdr->mStorageSize = aSize;
111 }
112
113 return aHdr;
114}
115
116nsStringBuffer* nsStringBuffer::FromString(const nsAString& aStr) {
117 if (!(aStr.mDataFlags & nsAString::DataFlags::REFCOUNTED)) {
118 return nullptr;
119 }
120
121 return FromData(aStr.mData);
122}
123
124nsStringBuffer* nsStringBuffer::FromString(const nsACString& aStr) {
125 if (!(aStr.mDataFlags & nsACString::DataFlags::REFCOUNTED)) {
126 return nullptr;
127 }
128
129 return FromData(aStr.mData);
130}
131
132void nsStringBuffer::ToString(uint32_t aLen, nsAString& aStr,
133 bool aMoveOwnership) {
134 char16_t* data = static_cast<char16_t*>(Data());
135
136 MOZ_DIAGNOSTIC_ASSERT(data[aLen] == char16_t(0),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(data[aLen] == char16_t(0))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(data[aLen] == char16_t(0))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("data[aLen] == char16_t(0)"
" (" "data should be null terminated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 137); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "data[aLen] == char16_t(0)"
") (" "data should be null terminated" ")"); do { *((volatile
int*)__null) = 137; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
137 "data should be null terminated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(data[aLen] == char16_t(0))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(data[aLen] == char16_t(0))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("data[aLen] == char16_t(0)"
" (" "data should be null terminated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 137); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "data[aLen] == char16_t(0)"
") (" "data should be null terminated" ")"); do { *((volatile
int*)__null) = 137; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
138
139 nsAString::DataFlags flags =
140 nsAString::DataFlags::REFCOUNTED | nsAString::DataFlags::TERMINATED;
141
142 if (!aMoveOwnership) {
143 AddRef();
144 }
145 aStr.Finalize();
146 aStr.SetData(data, aLen, flags);
147}
148
149void nsStringBuffer::ToString(uint32_t aLen, nsACString& aStr,
150 bool aMoveOwnership) {
151 char* data = static_cast<char*>(Data());
152
153 MOZ_DIAGNOSTIC_ASSERT(data[aLen] == char(0),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(data[aLen] == char(0))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(data[aLen] == char(0)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("data[aLen] == char(0)"
" (" "data should be null terminated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 154); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "data[aLen] == char(0)"
") (" "data should be null terminated" ")"); do { *((volatile
int*)__null) = 154; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
154 "data should be null terminated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(data[aLen] == char(0))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(data[aLen] == char(0)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("data[aLen] == char(0)"
" (" "data should be null terminated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/xpcom/string/nsStringBuffer.cpp"
, 154); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "data[aLen] == char(0)"
") (" "data should be null terminated" ")"); do { *((volatile
int*)__null) = 154; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
155
156 nsACString::DataFlags flags =
157 nsACString::DataFlags::REFCOUNTED | nsACString::DataFlags::TERMINATED;
158
159 if (!aMoveOwnership) {
160 AddRef();
161 }
162 aStr.Finalize();
163 aStr.SetData(data, aLen, flags);
164}
165
166size_t nsStringBuffer::SizeOfIncludingThisIfUnshared(
167 mozilla::MallocSizeOf aMallocSizeOf) const {
168 return IsReadonly() ? 0 : aMallocSizeOf(this);
169}
170
171size_t nsStringBuffer::SizeOfIncludingThisEvenIfShared(
172 mozilla::MallocSizeOf aMallocSizeOf) const {
173 return aMallocSizeOf(this);
174}