Skip to content

Commit

Permalink
Bug 1543295 - Pass the text length when creating an nsString from a…
Browse files Browse the repository at this point in the history
… SQLite text result. r=mak

This commit updates mozStorage to always:

* Pass the length, using sqlite3_{column, value}_bytes16, when
  creating an nsDependentString from a pointer.
* Call sqlite3_{column, value}_bytes{16} after
  sqlite3_{column, value}_{text, blob, text16}, per the
  recommendation in https://www.sqlite.org/c3ref/column_blob.html.
  Some callers did this before, or in unclear order, since C++ doesn't
  specify one for evaluating function arguments.
* Pass the byte length to sqlite3_result_text16.

Differential Revision: https://phabricator.services.mozilla.com/D26848

--HG--
extra : moz-landing-system : lando
  • Loading branch information
linabutler committed Apr 11, 2019
1 parent 4bbb97b commit 9dee251
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 51 deletions.
7 changes: 5 additions & 2 deletions storage/FileSystemModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,11 @@ int Filter(sqlite3_vtab_cursor* aCursor, int aIdxNum, const char* aIdxStr,
return SQLITE_OK;
}

nsDependentString path(
reinterpret_cast<const char16_t*>(::sqlite3_value_text16(aArgv[0])));
const char16_t* value =
static_cast<const char16_t*>(::sqlite3_value_text16(aArgv[0]));

nsDependentString path(value,
::sqlite3_value_bytes16(aArgv[0]) / sizeof(char16_t));

nsresult rv = cursor->Init(path);
NS_ENSURE_SUCCESS(rv, SQLITE_ERROR);
Expand Down
17 changes: 13 additions & 4 deletions storage/mozIStorageStatement.idl
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,20 @@ interface mozIStorageStatement : mozIStorageBaseStatement {
boolean getIsNull(in unsigned long aIndex);

/**
* Returns a shared string pointer
* Returns a shared string pointer.
*
* @param aIndex
* 0-based colummn index.
* @param aByteLength
* The number of bytes in the string or blob. This is the same as the
* number of characters for UTF-8 strings, and twice the number of
* characters for UTF-16 strings.
* @param aResult
* A pointer to the string or blob.
*/
[noscript] void getSharedUTF8String(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out string aResult);
[noscript] void getSharedString(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out wstring aResult);
[noscript] void getSharedBlob(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out octetPtr aResult);
[noscript] void getSharedUTF8String(in unsigned long aIndex, out unsigned long aByteLength, [shared,retval] out string aResult);
[noscript] void getSharedString(in unsigned long aIndex, out unsigned long aByteLength, [shared,retval] out wstring aResult);
[noscript] void getSharedBlob(in unsigned long aIndex, out unsigned long aByteLength, [shared,retval] out octetPtr aResult);

%{C++
/**
Expand Down
17 changes: 13 additions & 4 deletions storage/mozIStorageValueArray.idl
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,20 @@ interface mozIStorageValueArray : nsISupports {
boolean getIsNull(in unsigned long aIndex);

/**
* Returns a shared string pointer
* Returns a shared string pointer.
*
* @param aIndex
* 0-based colummn index.
* @param aByteLength
* The number of bytes in the string or blob. This is the same as the
* number of characters for UTF-8 strings, and twice the number of
* characters for UTF-16 strings.
* @param aResult
* A pointer to the string or blob.
*/
[noscript] void getSharedUTF8String(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out string aResult);
[noscript] void getSharedString(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out wstring aResult);
[noscript] void getSharedBlob(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out octetPtr aResult);
[noscript] void getSharedUTF8String(in unsigned long aIndex, out unsigned long aByteLength, [shared,retval] out string aResult);
[noscript] void getSharedString(in unsigned long aIndex, out unsigned long aByteLength, [shared,retval] out wstring aResult);
[noscript] void getSharedBlob(in unsigned long aIndex, out unsigned long aByteLength, [shared,retval] out octetPtr aResult);

%{C++
/**
Expand Down
27 changes: 16 additions & 11 deletions storage/mozStorageArgValueArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ ArgValueArray::GetString(uint32_t aIndex, nsAString &_value) {
// string.
_value.SetIsVoid(true);
} else {
_value.Assign(
static_cast<const char16_t *>(::sqlite3_value_text16(mArgv[aIndex])),
::sqlite3_value_bytes16(mArgv[aIndex]) / 2);
const char16_t *string =
static_cast<const char16_t *>(::sqlite3_value_text16(mArgv[aIndex]));
_value.Assign(string,
::sqlite3_value_bytes16(mArgv[aIndex]) / sizeof(char16_t));
}
return NS_OK;
}
Expand Down Expand Up @@ -148,30 +149,34 @@ ArgValueArray::GetIsNull(uint32_t aIndex, bool *_isNull) {
}

NS_IMETHODIMP
ArgValueArray::GetSharedUTF8String(uint32_t aIndex, uint32_t *_length,
ArgValueArray::GetSharedUTF8String(uint32_t aIndex, uint32_t *_byteLength,
const char **_string) {
if (_length) *_length = ::sqlite3_value_bytes(mArgv[aIndex]);

*_string =
reinterpret_cast<const char *>(::sqlite3_value_text(mArgv[aIndex]));
if (_byteLength) {
*_byteLength = ::sqlite3_value_bytes(mArgv[aIndex]);
}
return NS_OK;
}

NS_IMETHODIMP
ArgValueArray::GetSharedString(uint32_t aIndex, uint32_t *_length,
ArgValueArray::GetSharedString(uint32_t aIndex, uint32_t *_byteLength,
const char16_t **_string) {
if (_length) *_length = ::sqlite3_value_bytes(mArgv[aIndex]);

*_string =
static_cast<const char16_t *>(::sqlite3_value_text16(mArgv[aIndex]));
if (_byteLength) {
*_byteLength = ::sqlite3_value_bytes16(mArgv[aIndex]);
}
return NS_OK;
}

NS_IMETHODIMP
ArgValueArray::GetSharedBlob(uint32_t aIndex, uint32_t *_size,
ArgValueArray::GetSharedBlob(uint32_t aIndex, uint32_t *_byteLength,
const uint8_t **_blob) {
*_size = ::sqlite3_value_bytes(mArgv[aIndex]);
*_blob = static_cast<const uint8_t *>(::sqlite3_value_blob(mArgv[aIndex]));
if (_byteLength) {
*_byteLength = ::sqlite3_value_bytes(mArgv[aIndex]);
}
return NS_OK;
}

Expand Down
7 changes: 4 additions & 3 deletions storage/mozStorageBindingParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ int sqlite3_T_text(BindingColumnData aData, const nsCString &aValue) {
}

int sqlite3_T_text16(BindingColumnData aData, const nsString &aValue) {
return ::sqlite3_bind_text16(aData.stmt, aData.column + 1, aValue.get(),
aValue.Length() * 2, // Length in bytes!
SQLITE_TRANSIENT);
return ::sqlite3_bind_text16(
aData.stmt, aData.column + 1, aValue.get(),
aValue.Length() * sizeof(char16_t), // Length in bytes!
SQLITE_TRANSIENT);
}

int sqlite3_T_null(BindingColumnData aData) {
Expand Down
7 changes: 4 additions & 3 deletions storage/mozStorageConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,10 @@ int sqlite3_T_text(sqlite3_context *aCtx, const nsCString &aValue) {
}

int sqlite3_T_text16(sqlite3_context *aCtx, const nsString &aValue) {
::sqlite3_result_text16(aCtx, aValue.get(),
aValue.Length() * 2, // Number of bytes.
SQLITE_TRANSIENT);
::sqlite3_result_text16(
aCtx, aValue.get(),
aValue.Length() * sizeof(char16_t), // Number of bytes.
SQLITE_TRANSIENT);
return SQLITE_OK;
}

Expand Down
8 changes: 5 additions & 3 deletions storage/mozStorageRow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,19 @@ nsresult Row::initialize(sqlite3_stmt *aStatement) {
variant = new FloatVariant(::sqlite3_column_double(aStatement, i));
break;
case SQLITE_TEXT: {
nsDependentString str(static_cast<const char16_t *>(
::sqlite3_column_text16(aStatement, i)));
const char16_t *value = static_cast<const char16_t *>(
::sqlite3_column_text16(aStatement, i));
nsDependentString str(
value, ::sqlite3_column_bytes16(aStatement, i) / sizeof(char16_t));
variant = new TextVariant(str);
break;
}
case SQLITE_NULL:
variant = new NullVariant();
break;
case SQLITE_BLOB: {
int size = ::sqlite3_column_bytes(aStatement, i);
const void *data = ::sqlite3_column_blob(aStatement, i);
int size = ::sqlite3_column_bytes(aStatement, i);
variant = new BlobVariant(std::pair<const void *, int>(data, size));
break;
}
Expand Down
26 changes: 17 additions & 9 deletions storage/mozStorageSQLFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,10 @@ int registerFunctions(sqlite3 *aDB) {
void caseFunction(sqlite3_context *aCtx, int aArgc, sqlite3_value **aArgv) {
NS_ASSERTION(1 == aArgc, "Invalid number of arguments!");

nsAutoString data(
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[0])));
const char16_t *value =
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[0]));
nsAutoString data(value,
::sqlite3_value_bytes16(aArgv[0]) / sizeof(char16_t));
bool toUpper = ::sqlite3_user_data(aCtx) ? true : false;

if (toUpper)
Expand All @@ -270,7 +272,8 @@ void caseFunction(sqlite3_context *aCtx, int aArgc, sqlite3_value **aArgv) {
::ToLowerCase(data);

// Set the result.
::sqlite3_result_text16(aCtx, data.get(), -1, SQLITE_TRANSIENT);
::sqlite3_result_text16(aCtx, data.get(), data.Length() * sizeof(char16_t),
SQLITE_TRANSIENT);
}

/**
Expand All @@ -290,10 +293,15 @@ void likeFunction(sqlite3_context *aCtx, int aArgc, sqlite3_value **aArgv) {
if (!::sqlite3_value_text16(aArgv[0]) || !::sqlite3_value_text16(aArgv[1]))
return;

nsDependentString A(
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[1])));
nsDependentString B(
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[0])));
const char16_t *a =
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[1]));
int aLen = ::sqlite3_value_bytes16(aArgv[1]) / sizeof(char16_t);
nsDependentString A(a, aLen);

const char16_t *b =
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[0]));
int bLen = ::sqlite3_value_bytes16(aArgv[0]) / sizeof(char16_t);
nsDependentString B(b, bLen);
NS_ASSERTION(!B.IsEmpty(), "LIKE string must not be null!");

char16_t E = 0;
Expand Down Expand Up @@ -321,13 +329,13 @@ void levenshteinDistanceFunction(sqlite3_context *aCtx, int aArgc,
return;
}

int aLen = ::sqlite3_value_bytes16(aArgv[0]) / sizeof(char16_t);
const char16_t *a =
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[0]));
int aLen = ::sqlite3_value_bytes16(aArgv[0]) / sizeof(char16_t);

int bLen = ::sqlite3_value_bytes16(aArgv[1]) / sizeof(char16_t);
const char16_t *b =
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[1]));
int bLen = ::sqlite3_value_bytes16(aArgv[1]) / sizeof(char16_t);

// Compute the Levenshtein Distance, and return the result (or error).
int distance = -1;
Expand Down
28 changes: 17 additions & 11 deletions storage/mozStorageStatement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,8 @@ Statement::GetString(uint32_t aIndex, nsAString &_value) {
} else {
const char16_t *value = static_cast<const char16_t *>(
::sqlite3_column_text16(mDBStatement, aIndex));
_value.Assign(value, ::sqlite3_column_bytes16(mDBStatement, aIndex) / 2);
_value.Assign(value, ::sqlite3_column_bytes16(mDBStatement, aIndex) /
sizeof(char16_t));
}
return NS_OK;
}
Expand Down Expand Up @@ -700,8 +701,9 @@ Statement::GetVariant(uint32_t aIndex, nsIVariant **_value) {
case SQLITE_TEXT: {
const char16_t *value = static_cast<const char16_t *>(
::sqlite3_column_text16(mDBStatement, aIndex));
nsDependentString str(value,
::sqlite3_column_bytes16(mDBStatement, aIndex) / 2);
nsDependentString str(
value,
::sqlite3_column_bytes16(mDBStatement, aIndex) / sizeof(char16_t));
variant = new TextVariant(str);
break;
}
Expand Down Expand Up @@ -751,31 +753,35 @@ Statement::GetBlobAsUTF8String(uint32_t aIndex, nsACString &aValue) {
}

NS_IMETHODIMP
Statement::GetSharedUTF8String(uint32_t aIndex, uint32_t *_length,
Statement::GetSharedUTF8String(uint32_t aIndex, uint32_t *_byteLength,
const char **_value) {
if (_length) *_length = ::sqlite3_column_bytes(mDBStatement, aIndex);

*_value = reinterpret_cast<const char *>(
::sqlite3_column_text(mDBStatement, aIndex));
if (_byteLength) {
*_byteLength = ::sqlite3_column_bytes(mDBStatement, aIndex);
}
return NS_OK;
}

NS_IMETHODIMP
Statement::GetSharedString(uint32_t aIndex, uint32_t *_length,
Statement::GetSharedString(uint32_t aIndex, uint32_t *_byteLength,
const char16_t **_value) {
if (_length) *_length = ::sqlite3_column_bytes16(mDBStatement, aIndex);

*_value = static_cast<const char16_t *>(
::sqlite3_column_text16(mDBStatement, aIndex));
if (_byteLength) {
*_byteLength = ::sqlite3_column_bytes16(mDBStatement, aIndex);
}
return NS_OK;
}

NS_IMETHODIMP
Statement::GetSharedBlob(uint32_t aIndex, uint32_t *_size,
Statement::GetSharedBlob(uint32_t aIndex, uint32_t *_byteLength,
const uint8_t **_blob) {
*_size = ::sqlite3_column_bytes(mDBStatement, aIndex);
*_blob =
static_cast<const uint8_t *>(::sqlite3_column_blob(mDBStatement, aIndex));
if (_byteLength) {
*_byteLength = ::sqlite3_column_bytes(mDBStatement, aIndex);
}
return NS_OK;
}

Expand Down
3 changes: 2 additions & 1 deletion storage/mozStorageStatementRow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ void StatementRow::NamedGetter(JSContext* aCx, const nsAString& aName,
const char16_t* sval = reinterpret_cast<const char16_t*>(
static_cast<mozIStorageStatement*>(mStatement)
->AsSharedWString(idx, &bytes));
JSString* str = ::JS_NewUCStringCopyN(aCx, sval, bytes / 2);
JSString* str =
::JS_NewUCStringCopyN(aCx, sval, bytes / sizeof(char16_t));
if (!str) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
Expand Down

0 comments on commit 9dee251

Please sign in to comment.