Backed out 3 changesets (bug 335545) for asan failures in test_bug1123480.xul a=backout

Backed out changeset 25a686779a94 (bug 335545)
Backed out changeset b83ddb70c8b5 (bug 335545)
Backed out changeset ea69ee15ed90 (bug 335545)

MozReview-Commit-ID: LkJgt3eSs2J
This commit is contained in:
Wes Kocher 2017-09-26 15:26:07 -07:00
parent 5c22c4c93e
commit b3c0b118ec
4 changed files with 120 additions and 81 deletions

View File

@ -14,7 +14,6 @@ Notes to self:
#include "nsTransferable.h"
#include "nsAnonymousTemporaryFile.h"
#include "nsArray.h"
#include "nsArrayUtils.h"
#include "nsString.h"
@ -36,6 +35,7 @@ Notes to self:
#include "nsIOutputStream.h"
#include "nsIInputStream.h"
#include "nsIWeakReferenceUtils.h"
#include "nsIFile.h"
#include "nsILoadContext.h"
#include "mozilla/UniquePtr.h"
@ -55,9 +55,7 @@ size_t GetDataForFlavor (const nsTArray<DataStruct>& aArray,
//-------------------------------------------------------------------------
DataStruct::~DataStruct()
{
if (mCacheFD) {
PR_Close(mCacheFD);
}
if (mCacheFileName) free(mCacheFileName);
}
//-------------------------------------------------------------------------
@ -68,13 +66,10 @@ DataStruct::SetData ( nsISupports* aData, uint32_t aDataLen, bool aIsPrivateData
// as well as ensuring that private browsing mode is disabled
if (aDataLen > kLargeDatasetSize && !aIsPrivateData) {
// if so, cache it to disk instead of memory
if (NS_SUCCEEDED(WriteCache(aData, aDataLen))) {
// Clear previously set small data.
mData = nullptr;
mDataLen = 0;
if ( NS_SUCCEEDED(WriteCache(aData, aDataLen)) )
return;
}
NS_WARNING("Oh no, couldn't write data to the cache file");
else
NS_WARNING("Oh no, couldn't write data to the cache file");
}
mData = aData;
@ -87,7 +82,7 @@ void
DataStruct::GetData ( nsISupports** aData, uint32_t *aDataLen )
{
// check here to see if the data is cached on disk
if (mCacheFD) {
if ( !mData && mCacheFileName ) {
// if so, read it in and pass it back
// ReadCache creates memory and copies the data into it.
if ( NS_SUCCEEDED(ReadCache(aData, aDataLen)) )
@ -97,8 +92,6 @@ DataStruct::GetData ( nsISupports** aData, uint32_t *aDataLen )
NS_WARNING("Oh no, couldn't read data in from the cache file");
*aData = nullptr;
*aDataLen = 0;
PR_Close(mCacheFD);
mCacheFD = nullptr;
return;
}
}
@ -110,30 +103,65 @@ DataStruct::GetData ( nsISupports** aData, uint32_t *aDataLen )
}
//-------------------------------------------------------------------------
already_AddRefed<nsIFile>
DataStruct::GetFileSpec(const char* aFileName)
{
nsCOMPtr<nsIFile> cacheFile;
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(cacheFile));
if (!cacheFile)
return nullptr;
// if the param aFileName contains a name we should use that
// because the file probably already exists
// otherwise create a unique name
if (!aFileName) {
cacheFile->AppendNative(NS_LITERAL_CSTRING("clipboardcache"));
nsresult rv = cacheFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
if (NS_FAILED(rv))
return nullptr;
} else {
cacheFile->AppendNative(nsDependentCString(aFileName));
}
return cacheFile.forget();
}
//-------------------------------------------------------------------------
nsresult
DataStruct::WriteCache(nsISupports* aData, uint32_t aDataLen)
{
nsresult rv;
if (!mCacheFD) {
rv = NS_OpenAnonymousTemporaryFile(&mCacheFD);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
// Get a new path and file to the temp directory
nsCOMPtr<nsIFile> cacheFile = GetFileSpec(mCacheFileName);
if (cacheFile) {
// remember the file name
if (!mCacheFileName) {
nsCString fName;
cacheFile->GetNativeLeafName(fName);
mCacheFileName = strdup(fName.get());
}
}
// write out the contents of the clipboard to the file
void* buff = nullptr;
nsPrimitiveHelpers::CreateDataFromPrimitive(mFlavor, aData, &buff, aDataLen);
if (buff) {
int32_t written = PR_Write(mCacheFD, buff, aDataLen);
free(buff);
if (written) {
// write out the contents of the clipboard
// to the file
//uint32_t bytes;
nsCOMPtr<nsIOutputStream> outStr;
NS_NewLocalFileOutputStream(getter_AddRefs(outStr),
cacheFile);
if (!outStr) return NS_ERROR_FAILURE;
void* buff = nullptr;
nsPrimitiveHelpers::CreateDataFromPrimitive ( mFlavor, aData, &buff, aDataLen );
if ( buff ) {
uint32_t ignored;
outStr->Write(reinterpret_cast<char*>(buff), aDataLen, &ignored);
free(buff);
return NS_OK;
}
}
PR_Close(mCacheFD);
mCacheFD = nullptr;
return NS_ERROR_FAILURE;
}
@ -142,29 +170,49 @@ DataStruct::WriteCache(nsISupports* aData, uint32_t aDataLen)
nsresult
DataStruct::ReadCache(nsISupports** aData, uint32_t* aDataLen)
{
if (!mCacheFD) {
// if we don't have a cache filename we are out of luck
if (!mCacheFileName)
return NS_ERROR_FAILURE;
// get the path and file name
nsCOMPtr<nsIFile> cacheFile = GetFileSpec(mCacheFileName);
bool exists;
if ( cacheFile && NS_SUCCEEDED(cacheFile->Exists(&exists)) && exists ) {
// get the size of the file
int64_t fileSize;
int64_t max32 = 0xFFFFFFFF;
cacheFile->GetFileSize(&fileSize);
if (fileSize > max32)
return NS_ERROR_OUT_OF_MEMORY;
uint32_t size = uint32_t(fileSize);
// create new memory for the large clipboard data
auto data = mozilla::MakeUnique<char[]>(size);
if ( !data )
return NS_ERROR_OUT_OF_MEMORY;
// now read it all in
nsCOMPtr<nsIInputStream> inStr;
NS_NewLocalFileInputStream( getter_AddRefs(inStr),
cacheFile);
if (!cacheFile) return NS_ERROR_FAILURE;
nsresult rv = inStr->Read(data.get(), fileSize, aDataLen);
// make sure we got all the data ok
if (NS_SUCCEEDED(rv) && *aDataLen == size) {
nsPrimitiveHelpers::CreatePrimitiveForData(mFlavor, data.get(),
fileSize, aData);
return *aData ? NS_OK : NS_ERROR_FAILURE;
}
// zero the return params
*aData = nullptr;
*aDataLen = 0;
}
PRFileInfo fileInfo;
if (PR_GetOpenFileInfo(mCacheFD, &fileInfo) != PR_SUCCESS) {
return NS_ERROR_FAILURE;
}
uint32_t fileSize = fileInfo.size;
auto data = mozilla::MakeUnique<char[]>(fileSize);
if (!data) {
return NS_ERROR_OUT_OF_MEMORY;
}
uint32_t actual = PR_Read(mCacheFD, data.get(), fileSize);
// actual = 0 means end of file.
if (actual != 0 && actual != fileSize) {
return NS_ERROR_FAILURE;
}
nsPrimitiveHelpers::CreatePrimitiveForData(mFlavor, data.get(), fileSize, aData);
return NS_OK;
return NS_ERROR_FAILURE;
}

View File

@ -12,7 +12,6 @@
#include "nsString.h"
#include "nsTArray.h"
#include "nsIPrincipal.h"
#include "prio.h"
class nsIMutableArray;
@ -24,13 +23,14 @@ class nsIMutableArray;
struct DataStruct
{
explicit DataStruct ( const char* aFlavor )
: mDataLen(0), mCacheFD(nullptr), mFlavor(aFlavor) { }
: mDataLen(0), mFlavor(aFlavor), mCacheFileName(nullptr) { }
~DataStruct();
const nsCString& GetFlavor() const { return mFlavor; }
void SetData( nsISupports* inData, uint32_t inDataLen, bool aIsPrivateData );
void GetData( nsISupports** outData, uint32_t *outDataLen );
bool IsDataAvailable() const { return mData ? mDataLen > 0 : mCacheFD != nullptr; }
already_AddRefed<nsIFile> GetFileSpec(const char* aFileName);
bool IsDataAvailable() const { return (mData && mDataLen > 0) || (!mData && mCacheFileName); }
protected:
@ -43,11 +43,10 @@ protected:
nsresult WriteCache(nsISupports* aData, uint32_t aDataLen );
nsresult ReadCache(nsISupports** aData, uint32_t* aDataLen );
// mData + mDataLen OR mCacheFD should be used, not both.
nsCOMPtr<nsISupports> mData; // OWNER - some varient of primitive wrapper
uint32_t mDataLen;
PRFileDesc* mCacheFD;
const nsCString mFlavor;
char * mCacheFileName;
};

View File

@ -102,6 +102,5 @@ support-files = window_mouse_scroll_win.html
# Privacy relevant
[test_bug1123480.xul]
skip-if = os == "win" # test uses /dev/fd, which is only available on *NIX
subsuite = clipboard

View File

@ -13,45 +13,38 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1123480
<script type="application/javascript">
<![CDATA[
// Create 1 Mo of sample garbage text
// Since JS strings are saved as UTF16 strings, the string size is 2 MB,
// which is well above the kLargeDatasetSize threshold in nsTransferable.h
var Ipsum = "0123456789".repeat(100000);
var SHORT_STRING_NO_CACHE = "short string that will never be cached to the disk";
// Boilerplate constructs
var SmallDataset = 100000; // Hundred thousand bytes
// Get a list of open file descriptors, and ASSUME that any mutations in file
// descriptor counts are caused by our test. This is a bold assumption,
// but better than the alternatives (spawning lsof as a subprocess and parsing
// its output, or adding test-only code to nsAnonymousTemporaryFile).
function getOpenFileDescriptorCount() {
// Note: /dev/fd is only available on Linux and macOS, not Windows.
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
file.initWithPath("/dev/fd");
var count = 0;
for (var de = file.directoryEntries; de.hasMoreElements(); de.getNext()) {
++count;
}
return count;
// Create 1 Mo of sample garbage text
var Ipsum = ""; // Select text from this
for (var Iter = 0; Iter < SmallDataset; Iter++) {
Ipsum += Math.random().toString(36) + ' ';
}
function RunTest() {
const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
// Construct a nsIFile object for access to file methods
Components.utils.import("resource://gre/modules/FileUtils.jsm");
var clipboardFile = FileUtils.getFile("TmpD", ["clipboardcache"]);
// Sanitize environment
gClipboardHelper.copyString(SHORT_STRING_NO_CACHE);
var initialFdCount = getOpenFileDescriptorCount();
var expectedFdCount = initialFdCount + 1;
if (clipboardFile.exists()) {
clipboardFile.remove(false);
}
ok(!clipboardFile.exists(), "failed to presanitize the environment");
// Overflow a nsTransferable region by using the clipboard helper
const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
gClipboardHelper.copyString(Ipsum);
// Disabled private browsing mode should cache large selections to disk
is(getOpenFileDescriptorCount(), expectedFdCount, "correctly saved memory by caching to disk");
ok(clipboardFile.exists(), "correctly saved memory by caching to disk");
// Sanitize environment again
gClipboardHelper.copyString(SHORT_STRING_NO_CACHE);
is(getOpenFileDescriptorCount(), initialFdCount, "failed to evict the file descriptor of the clipboard cache");
if (clipboardFile.exists()) {
clipboardFile.remove(false);
}
ok(!clipboardFile.exists(), "failed to postsanitize the environment");
// Repeat procedure of plain text selection with private browsing enabled
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
@ -73,7 +66,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1123480
Services.clipboard.setData(Transfer, null, Services.clipboard.kGlobalClipboard);
// Enabled private browsing mode should not cache any selection to disk
is(getOpenFileDescriptorCount(), initialFdCount, "did not violate private browsing mode");
ok(!clipboardFile.exists(), "did not violate private browsing mode");
}
]]>
</script>