mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 590654 - Let JavaScript read embedded nulls from input streams
Adds a new method to NetUtil (readInputStreamToString) that will read a string with or without embedded NULLs from an input stream. Also adds the needed API on nsIScriptableInputStream to make this happen. r=bz sr=biesi a=blocking2.0
This commit is contained in:
parent
75637d22a2
commit
b3b7f224fd
@ -16,7 +16,7 @@
|
||||
* The Original Code is Mozilla code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
@ -257,6 +257,56 @@ const NetUtil = {
|
||||
return this.ioService.newChannelFromURI(uri);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reads aCount bytes from aInputStream into a string.
|
||||
*
|
||||
* @param aInputStream
|
||||
* The input stream to read from.
|
||||
* @param aCount
|
||||
* The number of bytes to read from the stream.
|
||||
*
|
||||
* @return the bytes from the input stream in string form.
|
||||
*
|
||||
* @throws NS_ERROR_INVALID_ARG if aInputStream is not an nsIInputStream.
|
||||
* @throws NS_BASE_STREAM_WOULD_BLOCK if reading from aInputStream would
|
||||
* block the calling thread (non-blocking mode only).
|
||||
* @throws NS_ERROR_FAILURE if there are not enough bytes available to read
|
||||
* aCount amount of data.
|
||||
*/
|
||||
readInputStreamToString: function NetUtil_readInputStreamToString(aInputStream,
|
||||
aCount)
|
||||
{
|
||||
if (!(aInputStream instanceof Ci.nsIInputStream)) {
|
||||
let exception = new Components.Exception(
|
||||
"First argument should be an nsIInputStream",
|
||||
Cr.NS_ERROR_INVALID_ARG,
|
||||
Components.stack.caller
|
||||
);
|
||||
throw exception;
|
||||
}
|
||||
|
||||
if (!aCount) {
|
||||
let exception = new Components.Exception(
|
||||
"Non-zero amount of bytes must be specified",
|
||||
Cr.NS_ERROR_INVALID_ARG,
|
||||
Components.stack.caller
|
||||
);
|
||||
throw exception;
|
||||
}
|
||||
|
||||
let sis = Cc["@mozilla.org/scriptableinputstream;1"].
|
||||
createInstance(Ci.nsIScriptableInputStream);
|
||||
sis.init(aInputStream);
|
||||
try {
|
||||
return sis.readBytes(aCount);
|
||||
}
|
||||
catch (e) {
|
||||
// Adjust the stack so it throws at the caller's location.
|
||||
throw new Components.Exception(e.message, e.result,
|
||||
Components.stack.caller, e.data);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a reference to nsIIOService.
|
||||
*
|
||||
|
@ -447,6 +447,83 @@ function test_newChannel_with_nsIFile()
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function test_readInputStreamToString()
|
||||
{
|
||||
const TEST_DATA = "this is a test string\0 with an embedded null";
|
||||
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
|
||||
createInstance(Ci.nsISupportsCString);
|
||||
istream.data = TEST_DATA;
|
||||
|
||||
do_check_eq(NetUtil.readInputStreamToString(istream, TEST_DATA.length),
|
||||
TEST_DATA);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function test_readInputStreamToString_no_input_stream()
|
||||
{
|
||||
try {
|
||||
NetUtil.readInputStreamToString("hi", 2);
|
||||
do_throw("should throw!");
|
||||
}
|
||||
catch (e) {
|
||||
do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function test_readInputStreamToString_no_bytes_arg()
|
||||
{
|
||||
const TEST_DATA = "this is a test string";
|
||||
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
|
||||
createInstance(Ci.nsIStringInputStream);
|
||||
istream.setData(TEST_DATA, TEST_DATA.length);
|
||||
|
||||
try {
|
||||
NetUtil.readInputStreamToString(istream);
|
||||
do_throw("should throw!");
|
||||
}
|
||||
catch (e) {
|
||||
do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function test_readInputStreamToString_blocking_stream()
|
||||
{
|
||||
let pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
|
||||
pipe.init(true, true, 0, 0, null);
|
||||
|
||||
try {
|
||||
NetUtil.readInputStreamToString(pipe.inputStream, 10);
|
||||
do_throw("should throw!");
|
||||
}
|
||||
catch (e) {
|
||||
do_check_eq(e.result, Cr.NS_BASE_STREAM_WOULD_BLOCK);
|
||||
}
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function test_readInputStreamToString_too_many_bytes()
|
||||
{
|
||||
const TEST_DATA = "this is a test string";
|
||||
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
|
||||
createInstance(Ci.nsIStringInputStream);
|
||||
istream.setData(TEST_DATA, TEST_DATA.length);
|
||||
|
||||
try {
|
||||
NetUtil.readInputStreamToString(istream, TEST_DATA.length + 10);
|
||||
do_throw("should throw!");
|
||||
}
|
||||
catch (e) {
|
||||
do_check_eq(e.result, Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Test Runner
|
||||
|
||||
@ -468,6 +545,11 @@ let tests = [
|
||||
test_newChannel_with_string,
|
||||
test_newChannel_with_nsIURI,
|
||||
test_newChannel_with_nsIFile,
|
||||
test_readInputStreamToString,
|
||||
test_readInputStreamToString_no_input_stream,
|
||||
test_readInputStreamToString_no_bytes_arg,
|
||||
test_readInputStreamToString_blocking_stream,
|
||||
test_readInputStreamToString_too_many_bytes,
|
||||
];
|
||||
let index = 0;
|
||||
|
||||
@ -475,15 +557,17 @@ function run_next_test()
|
||||
{
|
||||
if (index < tests.length) {
|
||||
do_test_pending();
|
||||
print("Running the next test: " + tests[index].name);
|
||||
|
||||
// Asynchronous test exceptions do not kill the test...
|
||||
try {
|
||||
tests[index++]();
|
||||
}
|
||||
catch (e) {
|
||||
do_throw(e);
|
||||
}
|
||||
do_execute_soon(function() {
|
||||
try {
|
||||
print("Running the next test: " + tests[index].name);
|
||||
tests[index++]();
|
||||
}
|
||||
catch (e) {
|
||||
do_throw(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
do_test_finished();
|
||||
|
@ -44,7 +44,7 @@ interface nsIInputStream;
|
||||
* nsIScriptableInputStream provides scriptable access to an nsIInputStream
|
||||
* instance.
|
||||
*/
|
||||
[scriptable, uuid(a2a32f90-9b90-11d3-a189-0050041caf44)]
|
||||
[scriptable, uuid(e546afd6-1248-4deb-8940-4b000b618a58)]
|
||||
interface nsIScriptableInputStream : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -82,4 +82,19 @@ interface nsIScriptableInputStream : nsISupports
|
||||
* @throws NS_ERROR_NOT_INITIALIZED if init was not called
|
||||
*/
|
||||
string read(in unsigned long aCount);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read data from the stream, including NULL bytes.
|
||||
*
|
||||
* @param aCount the maximum number of bytes to read.
|
||||
*
|
||||
* @return the data from the stream, which will be an empty string if EOF
|
||||
* has been reached.
|
||||
*
|
||||
* @throws NS_BASE_STREAM_WOULD_BLOCK if reading from the input stream
|
||||
* would block the calling thread (non-blocking mode only).
|
||||
* @throws NS_ERROR_FAILURE if there are not enough bytes available to read
|
||||
* aCount amount of data.
|
||||
*/
|
||||
ACString readBytes(in unsigned long aCount);
|
||||
};
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "nsScriptableInputStream.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsScriptableInputStream, nsIScriptableInputStream)
|
||||
|
||||
@ -88,6 +89,43 @@ nsScriptableInputStream::Read(PRUint32 aCount, char **_retval) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptableInputStream::ReadBytes(PRUint32 aCount, nsACString &_retval) {
|
||||
if (!mInputStream) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
_retval.SetLength(aCount);
|
||||
if (_retval.Length() != aCount) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
char *ptr = _retval.BeginWriting();
|
||||
PRUint32 totalBytesRead = 0;
|
||||
while (1) {
|
||||
PRUint32 bytesRead;
|
||||
nsresult rv = mInputStream->Read(ptr + totalBytesRead,
|
||||
aCount - totalBytesRead,
|
||||
&bytesRead);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
totalBytesRead += bytesRead;
|
||||
if (totalBytesRead == aCount) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If we have read zero bytes, we have hit EOF.
|
||||
if (bytesRead == 0) {
|
||||
_retval.Truncate();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptableInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
|
||||
if (aOuter) return NS_ERROR_NO_AGGREGATION;
|
||||
|
Loading…
Reference in New Issue
Block a user