Bug 1902439 - Checks return of nsIOutputStream::Write() to NS_OK in WriteBitmap() to handle failures better. r=mpohle,nrishel

Differential Revision: https://phabricator.services.mozilla.com/D234318
This commit is contained in:
jilvin
2025-05-20 17:35:17 +00:00
committed by nrishel@mozilla.com
parent 961b5b96ff
commit 0e104cbe54

View File

@@ -616,39 +616,55 @@ static nsresult WriteBitmap(nsIFile* aFile, imgIContainer* aImage) {
rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
NS_ENSURE_SUCCESS(rv, rv);
gfx::DataSourceSurface::MappedSurface map;
if (!dataSurface->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
// (redundant) guard clause to assert stream is initialized
if (NS_WARN_IF(!stream)) {
MOZ_ASSERT(stream, "rv should have failed when stream is not initialized.");
return NS_ERROR_FAILURE;
}
// write the bitmap headers and rgb pixel data to the file
rv = NS_ERROR_FAILURE;
if (stream) {
gfx::DataSourceSurface::MappedSurface map;
if (!dataSurface->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
// removal of file created handled later
rv = NS_ERROR_FAILURE;
}
// enter only if datasurface mapping succeeded
if (NS_SUCCEEDED(rv)) {
// write the bitmap headers and rgb pixel data to the file
uint32_t written;
stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
if (written == sizeof(BITMAPFILEHEADER)) {
stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written);
if (written == sizeof(BITMAPINFOHEADER)) {
rv = stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
if (NS_SUCCEEDED(rv)) {
rv = stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written);
if (NS_SUCCEEDED(rv)) {
// write out the image data backwards because the desktop won't
// show bitmaps with negative heights for top-to-bottom
uint32_t i = map.mStride * height;
do {
i -= map.mStride;
stream->Write(((const char*)map.mData) + i, bytesPerRow, &written);
if (written == bytesPerRow) {
rv = NS_OK;
} else {
rv = NS_ERROR_FAILURE;
rv = stream->Write(((const char*)map.mData) + i, bytesPerRow,
&written);
if (NS_FAILED(rv)) {
break;
}
} while (i != 0);
}
}
stream->Close();
dataSurface->Unmap();
}
dataSurface->Unmap();
stream->Close();
// Obtaining the file output stream results in a newly created file or
// truncates the file if it already exists. As such, it is necessary to
// remove the file if the write fails for some reason.
if (NS_FAILED(rv)) {
if (NS_WARN_IF(NS_FAILED(aFile->Remove(PR_FALSE)))) {
MOZ_LOG(sLog, LogLevel::Warning,
("Failed to remove empty bitmap file : %s",
aFile->HumanReadablePath().get()));
}
}
return rv;
}