mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-05 13:45:46 +00:00
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:
parent
5c22c4c93e
commit
b3c0b118ec
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user