Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp
Warning:line 164, column 12
Although the value stored to 'typeTest' is used in the enclosing expression, the value is never actually read from 'typeTest'

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 Unified_cpp_dom_xslt_xpath2.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=all -relaxed-aliasing -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -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 -D DEBUG=1 -D STATIC_EXPORTABLE_JS_API -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/xslt/xpath -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xml -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xslt -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 -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -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 -Os -Wwrite-strings -Wno-invalid-offsetof -Wno-error=maybe-uninitialized -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=coverage-mismatch -Wno-error=free-nonheap-object -Wno-error=shadow -fdeprecated-macro -fdebug-compilation-dir /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/xslt/xpath -ferror-limit 19 -fmessage-length 0 -stack-protector 2 -fno-rtti -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-checker optin.cplusplus.UninitializedObject -analyzer-checker alpha.cplusplus.IteratorRange -analyzer-checker alpha.core.BoolAssignment -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2019-10-10-015354-10307-1 -x c++ Unified_cpp_dom_xslt_xpath2.cpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6#include "mozilla/Assertions.h"
7#include "txXPathOptimizer.h"
8#include "txExprResult.h"
9#include "nsAtom.h"
10#include "nsGkAtoms.h"
11#include "txXPathNode.h"
12#include "txExpr.h"
13#include "txIXPathContext.h"
14
15class txEarlyEvalContext : public txIEvalContext {
16 public:
17 explicit txEarlyEvalContext(txResultRecycler* aRecycler)
18 : mRecycler(aRecycler) {}
19
20 // txIEvalContext
21 nsresult getVariable(int32_t aNamespace, nsAtom* aLName,
22 txAExprResult*& aResult) override {
23 MOZ_CRASH("shouldn't depend on this context")do { MOZ_ReportCrash("" "shouldn't depend on this context", "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 23); AnnotateMozCrashReason("MOZ_CRASH(" "shouldn't depend on this context"
")"); do { *((volatile int*)__null) = 23; ::abort(); } while
(false); } while (false)
;
24 }
25 nsresult isStripSpaceAllowed(const txXPathNode& aNode,
26 bool& aAllowed) override {
27 MOZ_CRASH("shouldn't depend on this context")do { MOZ_ReportCrash("" "shouldn't depend on this context", "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 27); AnnotateMozCrashReason("MOZ_CRASH(" "shouldn't depend on this context"
")"); do { *((volatile int*)__null) = 27; ::abort(); } while
(false); } while (false)
;
28 }
29 void* getPrivateContext() override {
30 MOZ_CRASH("shouldn't depend on this context")do { MOZ_ReportCrash("" "shouldn't depend on this context", "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 30); AnnotateMozCrashReason("MOZ_CRASH(" "shouldn't depend on this context"
")"); do { *((volatile int*)__null) = 30; ::abort(); } while
(false); } while (false)
;
31 }
32 txResultRecycler* recycler() override { return mRecycler; }
33 void receiveError(const nsAString& aMsg, nsresult aRes) override {}
34 const txXPathNode& getContextNode() override {
35 MOZ_CRASH("shouldn't depend on this context")do { MOZ_ReportCrash("" "shouldn't depend on this context", "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 35); AnnotateMozCrashReason("MOZ_CRASH(" "shouldn't depend on this context"
")"); do { *((volatile int*)__null) = 35; ::abort(); } while
(false); } while (false)
;
36 }
37 uint32_t size() override { MOZ_CRASH("shouldn't depend on this context")do { MOZ_ReportCrash("" "shouldn't depend on this context", "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 37); AnnotateMozCrashReason("MOZ_CRASH(" "shouldn't depend on this context"
")"); do { *((volatile int*)__null) = 37; ::abort(); } while
(false); } while (false)
; }
38 uint32_t position() override {
39 MOZ_CRASH("shouldn't depend on this context")do { MOZ_ReportCrash("" "shouldn't depend on this context", "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 39); AnnotateMozCrashReason("MOZ_CRASH(" "shouldn't depend on this context"
")"); do { *((volatile int*)__null) = 39; ::abort(); } while
(false); } while (false)
;
40 }
41
42 private:
43 txResultRecycler* mRecycler;
44};
45
46nsresult txXPathOptimizer::optimize(Expr* aInExpr, Expr** aOutExpr) {
47 *aOutExpr = nullptr;
48 nsresult rv = NS_OK;
49
50 // First check if the expression will produce the same result
51 // under any context.
52 Expr::ExprType exprType = aInExpr->getType();
53 if (exprType != Expr::LITERAL_EXPR &&
54 !aInExpr->isSensitiveTo(Expr::ANY_CONTEXT)) {
55 RefPtr<txResultRecycler> recycler = new txResultRecycler;
56 txEarlyEvalContext context(recycler);
57 RefPtr<txAExprResult> exprRes;
58
59 // Don't throw if this fails since it could be that the expression
60 // is or contains an error-expression.
61 rv = aInExpr->evaluate(&context, getter_AddRefs(exprRes));
62 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
63 *aOutExpr = new txLiteralExpr(exprRes);
64 }
65
66 return NS_OK;
67 }
68
69 // Then optimize sub expressions
70 uint32_t i = 0;
71 Expr* subExpr;
72 while ((subExpr = aInExpr->getSubExprAt(i))) {
73 Expr* newExpr = nullptr;
74 rv = optimize(subExpr, &newExpr);
75 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { mozilla::SmprintfPointer msg = mozilla::Smprintf
( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X", "rv"
, "rv", static_cast<uint32_t>(__rv)); NS_DebugBreak(NS_DEBUG_WARNING
, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 75); return rv; } } while (false)
;
76 if (newExpr) {
77 delete subExpr;
78 aInExpr->setSubExprAt(i, newExpr);
79 }
80
81 ++i;
82 }
83
84 // Finally see if current expression can be optimized
85 switch (exprType) {
86 case Expr::LOCATIONSTEP_EXPR:
87 return optimizeStep(aInExpr, aOutExpr);
88
89 case Expr::PATH_EXPR:
90 return optimizePath(aInExpr, aOutExpr);
91
92 case Expr::UNION_EXPR:
93 return optimizeUnion(aInExpr, aOutExpr);
94
95 default:
96 break;
97 }
98
99 return NS_OK;
100}
101
102nsresult txXPathOptimizer::optimizeStep(Expr* aInExpr, Expr** aOutExpr) {
103 LocationStep* step = static_cast<LocationStep*>(aInExpr);
104
105 if (step->getAxisIdentifier() == LocationStep::ATTRIBUTE_AXIS) {
106 // Test for @foo type steps.
107 txNameTest* nameTest = nullptr;
108 if (!step->getSubExprAt(0) &&
109 step->getNodeTest()->getType() == txNameTest::NAME_TEST &&
110 (nameTest = static_cast<txNameTest*>(step->getNodeTest()))
111 ->mLocalName != nsGkAtoms::_asterisk) {
112 *aOutExpr = new txNamedAttributeStep(
113 nameTest->mNamespace, nameTest->mPrefix, nameTest->mLocalName);
114 return NS_OK; // return since we no longer have a step-object.
115 }
116 }
117
118 // Test for predicates that can be combined into the nodetest
119 Expr* pred;
120 while ((pred = step->getSubExprAt(0)) &&
121 !pred->canReturnType(Expr::NUMBER_RESULT) &&
122 !pred->isSensitiveTo(Expr::NODESET_CONTEXT)) {
123 txNodeTest* predTest = new txPredicatedNodeTest(step->getNodeTest(), pred);
124 step->dropFirst();
125 step->setNodeTest(predTest);
126 }
127
128 return NS_OK;
129}
130
131nsresult txXPathOptimizer::optimizePath(Expr* aInExpr, Expr** aOutExpr) {
132 PathExpr* path = static_cast<PathExpr*>(aInExpr);
133
134 uint32_t i;
135 Expr* subExpr;
136 // look for steps like "//foo" that can be turned into "/descendant::foo"
137 // and "//." that can be turned into "/descendant-or-self::node()"
138 for (i = 0; (subExpr = path->getSubExprAt(i)); ++i) {
139 if (path->getPathOpAt(i) == PathExpr::DESCENDANT_OP &&
140 subExpr->getType() == Expr::LOCATIONSTEP_EXPR &&
141 !subExpr->getSubExprAt(0)) {
142 LocationStep* step = static_cast<LocationStep*>(subExpr);
143 if (step->getAxisIdentifier() == LocationStep::CHILD_AXIS) {
144 step->setAxisIdentifier(LocationStep::DESCENDANT_AXIS);
145 path->setPathOpAt(i, PathExpr::RELATIVE_OP);
146 } else if (step->getAxisIdentifier() == LocationStep::SELF_AXIS) {
147 step->setAxisIdentifier(LocationStep::DESCENDANT_OR_SELF_AXIS);
148 path->setPathOpAt(i, PathExpr::RELATIVE_OP);
149 }
150 }
151 }
152
153 // look for expressions that start with a "./"
154 subExpr = path->getSubExprAt(0);
155 LocationStep* step;
156 if (subExpr->getType() == Expr::LOCATIONSTEP_EXPR && path->getSubExprAt(1) &&
157 path->getPathOpAt(1) != PathExpr::DESCENDANT_OP) {
158 step = static_cast<LocationStep*>(subExpr);
159 if (step->getAxisIdentifier() == LocationStep::SELF_AXIS &&
160 !step->getSubExprAt(0)) {
161 txNodeTest* test = step->getNodeTest();
162 txNodeTypeTest* typeTest;
163 if (test->getType() == txNodeTest::NODETYPE_TEST &&
164 (typeTest = static_cast<txNodeTypeTest*>(test))->getNodeTestType() ==
Although the value stored to 'typeTest' is used in the enclosing expression, the value is never actually read from 'typeTest'
165 txNodeTypeTest::NODE_TYPE) {
166 // We have a '.' as first step followed by a single '/'.
167
168 // Check if there are only two steps. If so, return the second
169 // as resulting expression.
170 if (!path->getSubExprAt(2)) {
171 *aOutExpr = path->getSubExprAt(1);
172 path->setSubExprAt(1, nullptr);
173
174 return NS_OK;
175 }
176
177 // Just delete the '.' step and leave the rest of the PathExpr
178 path->deleteExprAt(0);
179 }
180 }
181 }
182
183 return NS_OK;
184}
185
186nsresult txXPathOptimizer::optimizeUnion(Expr* aInExpr, Expr** aOutExpr) {
187 UnionExpr* uni = static_cast<UnionExpr*>(aInExpr);
188
189 // Check for expressions like "foo | bar" and
190 // "descendant::foo | descendant::bar"
191
192 nsresult rv;
193 uint32_t current;
194 Expr* subExpr;
195 for (current = 0; (subExpr = uni->getSubExprAt(current)); ++current) {
196 if (subExpr->getType() != Expr::LOCATIONSTEP_EXPR ||
197 subExpr->getSubExprAt(0)) {
198 continue;
199 }
200
201 LocationStep* currentStep = static_cast<LocationStep*>(subExpr);
202 LocationStep::LocationStepType axis = currentStep->getAxisIdentifier();
203
204 txUnionNodeTest* unionTest = nullptr;
205
206 // Check if there are any other steps with the same axis and merge
207 // them with currentStep
208 uint32_t i;
209 for (i = current + 1; (subExpr = uni->getSubExprAt(i)); ++i) {
210 if (subExpr->getType() != Expr::LOCATIONSTEP_EXPR ||
211 subExpr->getSubExprAt(0)) {
212 continue;
213 }
214
215 LocationStep* step = static_cast<LocationStep*>(subExpr);
216 if (step->getAxisIdentifier() != axis) {
217 continue;
218 }
219
220 // Create a txUnionNodeTest if needed
221 if (!unionTest) {
222 nsAutoPtr<txNodeTest> owner(unionTest = new txUnionNodeTest);
223 rv = unionTest->addNodeTest(currentStep->getNodeTest());
224 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { mozilla::SmprintfPointer msg = mozilla::Smprintf
( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X", "rv"
, "rv", static_cast<uint32_t>(__rv)); NS_DebugBreak(NS_DEBUG_WARNING
, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 224); return rv; } } while (false)
;
225
226 currentStep->setNodeTest(unionTest);
227 owner.forget();
228 }
229
230 // Merge the nodetest into the union
231 rv = unionTest->addNodeTest(step->getNodeTest());
232 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { mozilla::SmprintfPointer msg = mozilla::Smprintf
( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X", "rv"
, "rv", static_cast<uint32_t>(__rv)); NS_DebugBreak(NS_DEBUG_WARNING
, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath/txXPathOptimizer.cpp"
, 232); return rv; } } while (false)
;
233
234 step->setNodeTest(nullptr);
235
236 // Remove the step from the UnionExpr
237 uni->deleteExprAt(i);
238 --i;
239 }
240
241 // Check if all expressions were merged into a single step. If so,
242 // return the step as the new expression.
243 if (unionTest && current == 0 && !uni->getSubExprAt(1)) {
244 // Make sure the step doesn't get deleted when the UnionExpr is
245 uni->setSubExprAt(0, nullptr);
246 *aOutExpr = currentStep;
247
248 // Return right away since we no longer have a union
249 return NS_OK;
250 }
251 }
252
253 return NS_OK;
254}