Bug Summary

File:root/firefox-clang/third_party/zucchini/moz_zucchini.cc
Warning:line 75, column 3
Potential leak of memory pointed to by 'allocation'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name moz_zucchini.cc -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=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/zucchini -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/zucchini -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D _FILE_OFFSET_BITS=64 -D UNICODE -D ENABLED_VLOG_LEVEL=1 -D MOZ_NEUTER_SEH_FOR_MINGWCLANG -I /root/firefox-clang/third_party/zucchini -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/zucchini -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/third_party/googletest/googletest/include -I /root/firefox-clang/third_party/zucchini/chromium-shim -I /root/firefox-clang/third_party/zucchini/chromium -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -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-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 -Wno-character-conversion -Wno-pragma-clang-attribute -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-11-12-001017-1011516-1 -x c++ /root/firefox-clang/third_party/zucchini/moz_zucchini.cc
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "mozilla/moz_zucchini.h"
8
9#include "absl/types/optional.h"
10#include "base/logging.h"
11#include "base/files/file.h"
12#include "base/files/file_util.h"
13#include "build/build_config.h"
14#include "components/zucchini/crc32.h"
15#include "components/zucchini/mapped_file.h"
16#include "components/zucchini/patch_reader.h"
17#include "components/zucchini/zucchini.h"
18#include "components/zucchini/zucchini_apply.h"
19
20#include <cstdio>
21#include <limits>
22#include <memory>
23#include <new>
24#include <string>
25
26#if BUILDFLAG(IS_WIN)((0))
27// Get EXCEPTION_* constants defined with DWORD type
28# include <ntstatus.h>
29
30# if defined(HAVE_SEH_EXCEPTIONS)
31# include "components/zucchini/exception_filter_helper_win.h"
32# endif // HAVE_SEH_EXCEPTIONS
33
34# include <io.h>
35#endif // BUILDFLAG(IS_WIN)
36
37namespace zucchini::mozilla {
38
39#ifdef ENABLE_TESTS1
40// Helpers for crash test scenarios.
41
42static TestOptions gTestOptions;
43
44void SetTestOptions(const TestOptions& aTestOptions) {
45 gTestOptions = aTestOptions;
46}
47
48// Test-only log to prove stack unwinding reaches local destructors when we
49// recover from a fault originating from inside zucchini.
50class ScopedDestructorMarker {
51 public:
52 ScopedDestructorMarker() = default;
53
54 ~ScopedDestructorMarker() {
55 if (!gTestOptions.logDestructorMarker) {
56 return;
57 }
58
59 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 59, ::logging::LOGGING_ERROR).stream())
<< "MOZ_TEST_ZUCCHINI_DTOR_MARKER";
60 }
61};
62
63// Test-only OOM injection used by updater tests to verify that a thrown
64// bad_alloc is translated into kStatusOutOfMemory.
65static void MaybeTriggerTestBadAlloc() {
66 if (!gTestOptions.triggerBadAlloc) {
10
Assuming field 'triggerBadAlloc' is true
11
Taking false branch
67 return;
68 }
69
70 // This allocation is expected to throw std::bad_alloc. volatile prevents
71 // the compiler from optimizing it away. If it somehow succeeded, CHECK(false)
72 // ensures the test fails visibly rather than silently passing.
73 void* volatile allocation = ::operator new(std::numeric_limits<size_t>::max());
12
Memory is allocated
74 (void)allocation;
75 CHECK(false)switch (0) case 0: default: if (const bool probably_true = static_cast
<bool>(false); __builtin_expect(!!(::AnalyzerAssumeTrue
(!!(probably_true))), 1)) ; else (::logging::CheckError::Check
("false"))
;
13
Control jumps to 'case 0:' at line 75
14
Potential leak of memory pointed to by 'allocation'
76}
77
78// Test-only CHECK() injection used by updater tests to verify that deliberate
79// crash paths are converted into kStatusFatal.
80static void MaybeTriggerTestCheckFailure() {
81 if (!gTestOptions.triggerCheckFailure) {
82 return;
83 }
84
85 CHECK(false)switch (0) case 0: default: if (const bool probably_true = static_cast
<bool>(false); __builtin_expect(!!(::AnalyzerAssumeTrue
(!!(probably_true))), 1)) ; else (::logging::CheckError::Check
("false"))
;
86}
87
88// Test-only injection of the exception that Windows raises when accessing a
89// mapped file fails, used by updater tests to verify that we recover from it
90// and release the mapped files. Writes fail because the disk is full, reads
91// because of a device error.
92static void MaybeTriggerTestPageError(bool aTrigger, const uint8_t* aAddress,
93 bool aIsWrite) {
94 if (!aTrigger) {
95 return;
96 }
97
98# if BUILDFLAG(IS_WIN)((0)) && defined(HAVE_SEH_EXCEPTIONS)
99 const ULONG_PTR info[3] = {
100 aIsWrite, reinterpret_cast<ULONG_PTR>(aAddress),
101 static_cast<ULONG_PTR>(aIsWrite ? STATUS_DISK_FULL
102 : STATUS_DEVICE_DATA_ERROR)};
103 ::RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, info);
104# endif // BUILDFLAG(IS_WIN) && HAVE_SEH_EXCEPTIONS
105}
106#endif // ENABLE_TESTS
107
108static LogFunctionPtr gLogFunction = nullptr;
109
110static bool LogMessageHandler(int aSeverity, const char* aFile, int aLine,
111 size_t aMessageStart, const std::string& aStr) {
112 if (!gLogFunction) {
113 return false;
114 }
115 gLogFunction(aStr.c_str());
116 return true;
117}
118
119void SetLogFunction(LogFunctionPtr aLogFunction) {
120 gLogFunction = aLogFunction;
121 logging::SetLogMessageHandler(LogMessageHandler);
122}
123
124#if !defined(__cpp_exceptions199711L)
125# error The zucchini interface code requires compiler support for C++ exceptions.
126#endif // !cpp_exceptions
127
128
129// Catch C++ exceptions raised within zucchini code. This lets the updater
130// recover from standard library allocation failures, so it can write an OOM
131// update.status and run post-failure cleanup. We wrap the entire body of
132// every entry point reachable from updater.cpp, making sure we cover all the
133// zucchini code it uses.
134//
135// Every entry point into zucchini thus returns a status code. Running into a
136// C++ std::bad_alloc exception returns kStatusOutOfMemory. Any other C++
137// exception results in kStatusFatal, although that should never happen.
138
139#define BEGIN_ENTRY_POINT()try { try {
140#define END_ENTRY_POINT()} catch (const std::bad_alloc&) { !((::logging::ShouldCreateLogMessage
(::logging::LOGGING_ERROR))) ? (void) 0 : ::logging::LogMessageVoidify
() & (::logging::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 140, ::logging::LOGGING_ERROR).stream()) << "std::bad_alloc caught in zucchini."
; return status::kStatusOutOfMemory; } catch (...) { !((::logging
::ShouldCreateLogMessage(::logging::LOGGING_ERROR))) ? (void)
0 : ::logging::LogMessageVoidify() & (::logging::LogMessage
("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc", 140
, ::logging::LOGGING_ERROR).stream()) << "unknown exception caught in zucchini; this is a bug."
; return status::kStatusFatal; }
\
141 } \
142 catch (const std::bad_alloc&) { \
143 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 143, ::logging::LOGGING_ERROR).stream())
<< "std::bad_alloc caught in zucchini."; \
144 return status::kStatusOutOfMemory; \
145 } \
146 catch (...) { \
147 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 147, ::logging::LOGGING_ERROR).stream())
<< "unknown exception caught in zucchini; this is a bug."; \
148 return status::kStatusFatal; \
149 }
150
151#if BUILDFLAG(IS_WIN)((0)) && defined(HAVE_SEH_EXCEPTIONS)
152static status::Code PageErrorStatus(const ExceptionFilterHelper& aHelper) {
153 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 153, ::logging::LOGGING_ERROR).stream())
<< "EXCEPTION_IN_PAGE_ERROR while "
154 << (aHelper.is_write() ? "writing to" : "reading from")
155 << " mapped files; NTSTATUS = " << aHelper.nt_status();
156 return aHelper.nt_status() == STATUS_DISK_FULL ? status::kStatusDiskFull
157 : status::kStatusIoError;
158}
159
160// Narrow handler that stays around the code touching the mapped file ranges,
161// where EXCEPTION_IN_PAGE_ERROR can be raised. Usable only within member
162// functions, as it relies on mImpl. This reflects the exception catching
163// present in upstream zucchini::ApplyCommon (zucchini_integration.cc).
164// Objects that need unwinding must live outside of aFunc: the unwinding that
165// follows an EXCEPTION_IN_PAGE_ERROR doesn't run their destructors.
166template <typename F>
167static status::Code GuardPageErrors(ExceptionFilterHelper& aHelper, F& aFunc) {
168 __trytry {
169 return aFunc();
170 } __except (
171 aHelper.FilterPageError(GetExceptionInformation()->ExceptionRecord)) {
172 return PageErrorStatus(aHelper);
173 }
174}
175# define GUARD_PAGE_ERRORS(aFunc)aFunc() \
176 GuardPageErrors(mImpl->mExceptionFilterHelper, aFunc)
177#else
178# define GUARD_PAGE_ERRORS(aFunc)aFunc() aFunc()
179#endif // BUILDFLAG(IS_WIN) && HAVE_SEH_EXCEPTIONS
180
181status::Code ComputeCrc32(const uint8_t* aBuf, size_t aBufSize,
182 uint32_t& aOutCrc32) {
183 BEGIN_ENTRY_POINT()try {
184 aOutCrc32 = CalculateCrc32(aBuf, aBuf + aBufSize);
185 return status::kStatusSuccess;
186 END_ENTRY_POINT()} catch (const std::bad_alloc&) { !((::logging::ShouldCreateLogMessage
(::logging::LOGGING_ERROR))) ? (void) 0 : ::logging::LogMessageVoidify
() & (::logging::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 186, ::logging::LOGGING_ERROR).stream()) << "std::bad_alloc caught in zucchini."
; return status::kStatusOutOfMemory; } catch (...) { !((::logging
::ShouldCreateLogMessage(::logging::LOGGING_ERROR))) ? (void)
0 : ::logging::LogMessageVoidify() & (::logging::LogMessage
("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc", 186
, ::logging::LOGGING_ERROR).stream()) << "unknown exception caught in zucchini; this is a bug."
; return status::kStatusFatal; }
187}
188
189class MappedPatchImpl {
190 public:
191 MappedPatchImpl() = default;
192 ~MappedPatchImpl() = default;
193 std::optional<MappedFileReader> mFileReader;
194 EnsemblePatchReader mPatchReader;
195#if BUILDFLAG(IS_WIN)((0)) && defined(HAVE_SEH_EXCEPTIONS)
196 ExceptionFilterHelper mExceptionFilterHelper;
197#endif // BUILDFLAG(IS_WIN) && HAVE_SEH_EXCEPTIONS
198};
199
200status::Code MappedPatch::Initialize() {
201 BEGIN_ENTRY_POINT()try {
202 mImpl = new MappedPatchImpl();
203 return status::kStatusSuccess;
204 END_ENTRY_POINT()} catch (const std::bad_alloc&) { !((::logging::ShouldCreateLogMessage
(::logging::LOGGING_ERROR))) ? (void) 0 : ::logging::LogMessageVoidify
() & (::logging::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 204, ::logging::LOGGING_ERROR).stream()) << "std::bad_alloc caught in zucchini."
; return status::kStatusOutOfMemory; } catch (...) { !((::logging
::ShouldCreateLogMessage(::logging::LOGGING_ERROR))) ? (void)
0 : ::logging::LogMessageVoidify() & (::logging::LogMessage
("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc", 204
, ::logging::LOGGING_ERROR).stream()) << "unknown exception caught in zucchini; this is a bug."
; return status::kStatusFatal; }
205}
206
207status::Code MappedPatch::Finalize() {
208 BEGIN_ENTRY_POINT()try {
209 auto* impl = mImpl;
210 mImpl = nullptr;
211 delete impl;
212 return status::kStatusSuccess;
213 END_ENTRY_POINT()} catch (const std::bad_alloc&) { !((::logging::ShouldCreateLogMessage
(::logging::LOGGING_ERROR))) ? (void) 0 : ::logging::LogMessageVoidify
() & (::logging::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 213, ::logging::LOGGING_ERROR).stream()) << "std::bad_alloc caught in zucchini."
; return status::kStatusOutOfMemory; } catch (...) { !((::logging
::ShouldCreateLogMessage(::logging::LOGGING_ERROR))) ? (void)
0 : ::logging::LogMessageVoidify() & (::logging::LogMessage
("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc", 213
, ::logging::LOGGING_ERROR).stream()) << "unknown exception caught in zucchini; this is a bug."
; return status::kStatusFatal; }
214}
215
216// This corresponds to the first half of zucchini::ApplyCommon.
217status::Code MappedPatch::LoadImpl(FILE* aPatchFile, uint32_t* aSourceSize,
218 uint32_t* aDestinationSize,
219 uint32_t* aSourceCrc32) {
220 base::File patchFile = base::FILEToFile(aPatchFile);
221 if (!patchFile.IsValid()) {
222 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 222, ::logging::LOGGING_ERROR).stream())
<< "Invalid patch file.";
223 return status::kStatusFileReadError;
224 }
225 mImpl->mFileReader.emplace(std::move(patchFile));
226 auto& fileReader = *mImpl->mFileReader;
227 if (fileReader.HasError()) {
228 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 228, ::logging::LOGGING_ERROR).stream())
<< "Error with patch file: " << fileReader.error();
229 if (fileReader.error_is_oom()) {
230 return status::kStatusOutOfMemory;
231 }
232 return status::kStatusFileReadError;
233 }
234#if BUILDFLAG(IS_WIN)((0)) && defined(HAVE_SEH_EXCEPTIONS)
235 mImpl->mExceptionFilterHelper.AddRange(
236 {fileReader.data(), fileReader.length()});
237#endif // BUILDFLAG(IS_WIN) && HAVE_SEH_EXCEPTIONS
238 auto readHeader = [&]() {
239#ifdef ENABLE_TESTS1
240 MaybeTriggerTestPageError(gTestOptions.triggerReadPageError,
241 fileReader.data(), /* aIsWrite */ false);
242#endif // ENABLE_TESTS
243 BufferSource source(fileReader.region());
244 auto& patchReader = mImpl->mPatchReader;
245 if (!patchReader.Initialize(&source)) {
246 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 246, ::logging::LOGGING_ERROR).stream())
<< "Error reading patch header.";
247 return status::kStatusPatchReadError;
248 }
249 auto& header = patchReader.header();
250 *aSourceSize = header.old_size;
251 *aDestinationSize = header.new_size;
252 *aSourceCrc32 = header.old_crc;
253 return status::kStatusSuccess;
254 };
255 return GUARD_PAGE_ERRORS(readHeader)readHeader();
256}
257
258status::Code MappedPatch::Load(FILE* aPatchFile, uint32_t* aSourceSize,
259 uint32_t* aDestinationSize,
260 uint32_t* aSourceCrc32) {
261 if (!mImpl) {
262 return mInitStatus;
263 }
264 BEGIN_ENTRY_POINT()try {
265 return LoadImpl(aPatchFile, aSourceSize, aDestinationSize, aSourceCrc32);
266 END_ENTRY_POINT()} catch (const std::bad_alloc&) { !((::logging::ShouldCreateLogMessage
(::logging::LOGGING_ERROR))) ? (void) 0 : ::logging::LogMessageVoidify
() & (::logging::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 266, ::logging::LOGGING_ERROR).stream()) << "std::bad_alloc caught in zucchini."
; return status::kStatusOutOfMemory; } catch (...) { !((::logging
::ShouldCreateLogMessage(::logging::LOGGING_ERROR))) ? (void)
0 : ::logging::LogMessageVoidify() & (::logging::LogMessage
("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc", 266
, ::logging::LOGGING_ERROR).stream()) << "unknown exception caught in zucchini; this is a bug."
; return status::kStatusFatal; }
267}
268
269// This is zucchini::ApplyBuffer, except that we *assume* that aCheckedOldImage
270// has the correct size and crc32 instead of checking it.
271static status::Code ApplyBufferUnsafe(ConstBufferView aCheckedOldImage,
272 const EnsemblePatchReader& aPatchReader,
273 MutableBufferView aNewImage) {
274#ifdef ENABLE_TESTS1
275 // We want updater tests to simulate zucchini failures occurring in the worst
276 // possible location from the updater recovery's point of view. Failing here
277 // simulates a failure in the middle of patch application, with the new image
278 // still open and mapped, which makes recovery quite subtle.
279 ScopedDestructorMarker destructorTester;
280 MaybeTriggerTestBadAlloc();
9
Calling 'MaybeTriggerTestBadAlloc'
281 MaybeTriggerTestCheckFailure();
282 MaybeTriggerTestPageError(gTestOptions.triggerWritePageError,
283 aNewImage.begin(), /* aIsWrite */ true);
284#endif // ENABLE_TESTS
285
286 for (const auto& elementPatch : aPatchReader.elements()) {
287 ElementMatch match = elementPatch.element_match();
288 if (!ApplyElement(match.exe_type(),
289 aCheckedOldImage[match.old_element.region()],
290 elementPatch, aNewImage[match.new_element.region()]))
291 return status::kStatusFatal;
292 }
293
294 if (!aPatchReader.CheckNewFile(ConstBufferView(aNewImage))) {
295 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 295, ::logging::LOGGING_ERROR).stream())
<< "Invalid aNewImage.";
296 return status::kStatusInvalidNewImage;
297 }
298
299 return status::kStatusSuccess;
300}
301
302// This corresponds to the second half of zucchini::ApplyCommon.
303status::Code MappedPatch::ApplyUnsafeImpl(const uint8_t* aCheckedOldImage,
304 size_t aCheckedOldImageSize,
305 FILE* aNewFile) {
306 ConstBufferView oldImageView(aCheckedOldImage, aCheckedOldImageSize);
307
308 base::File newFile = base::FILEToFile(aNewFile);
309 if (!newFile.IsValid()) {
4
Assuming the condition is false
5
Taking false branch
310 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 310, ::logging::LOGGING_ERROR).stream())
<< "Invalid new file.";
311 return status::kStatusFileWriteError;
312 }
313
314 PatchHeader header = mImpl->mPatchReader.header();
315 base::FilePath name = base::FilePath().AppendASCII("old_name");
316 MappedFileWriter mappedNew(name, std::move(newFile), header.new_size,
317 /*keep*/ true);
318 if (mappedNew.HasError()) {
6
Taking false branch
319 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 319, ::logging::LOGGING_ERROR).stream())
<< "Error with new file: " << mappedNew.error();
320 if (mappedNew.error_is_oom()) {
321 return status::kStatusOutOfMemory;
322 }
323 return status::kStatusFileWriteError;
324 }
325
326#if BUILDFLAG(IS_WIN)((0)) && defined(HAVE_SEH_EXCEPTIONS)
327 mImpl->mExceptionFilterHelper.AddRange(
328 {mappedNew.data(), mappedNew.length()});
329#endif // BUILDFLAG(IS_WIN) && HAVE_SEH_EXCEPTIONS
330
331 auto applyToNewFile = [&]() {
332 status::Code result = ApplyBufferUnsafe(oldImageView, mImpl->mPatchReader,
8
Calling 'ApplyBufferUnsafe'
333 mappedNew.region());
334 if (result != status::kStatusSuccess) {
335 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 335, ::logging::LOGGING_ERROR).stream())
<< "Fatal error encountered while applying patch.";
336 return result;
337 }
338
339 if (!mappedNew.Flush()) {
340 LOG(ERROR)!((::logging::ShouldCreateLogMessage(::logging::LOGGING_ERROR
))) ? (void) 0 : ::logging::LogMessageVoidify() & (::logging
::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 340, ::logging::LOGGING_ERROR).stream())
<< "Error flushing changes to disk: " << mappedNew.error();
341 return status::kStatusFileWriteError;
342 }
343
344 return status::kStatusSuccess;
345 };
346 return GUARD_PAGE_ERRORS(applyToNewFile)applyToNewFile();
7
Calling 'operator()'
347}
348
349status::Code MappedPatch::ApplyUnsafe(const uint8_t* aCheckedOldImage,
350 size_t aCheckedOldImageSize,
351 FILE* aNewFile) {
352 if (!mImpl) {
1
Assuming field 'mImpl' is non-null
2
Taking false branch
353 return mInitStatus;
354 }
355 BEGIN_ENTRY_POINT()try {
356 return ApplyUnsafeImpl(aCheckedOldImage, aCheckedOldImageSize, aNewFile);
3
Calling 'MappedPatch::ApplyUnsafeImpl'
357 END_ENTRY_POINT()} catch (const std::bad_alloc&) { !((::logging::ShouldCreateLogMessage
(::logging::LOGGING_ERROR))) ? (void) 0 : ::logging::LogMessageVoidify
() & (::logging::LogMessage("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc"
, 357, ::logging::LOGGING_ERROR).stream()) << "std::bad_alloc caught in zucchini."
; return status::kStatusOutOfMemory; } catch (...) { !((::logging
::ShouldCreateLogMessage(::logging::LOGGING_ERROR))) ? (void)
0 : ::logging::LogMessageVoidify() & (::logging::LogMessage
("/root/firefox-clang/third_party/zucchini/moz_zucchini.cc", 357
, ::logging::LOGGING_ERROR).stream()) << "unknown exception caught in zucchini; this is a bug."
; return status::kStatusFatal; }
358}
359
360} // namespace zucchini::mozilla