diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 80c068795671..ee53863456c9 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -4484,7 +4484,8 @@ struct AutoValue bool SizeToType(JSContext* cx, JSObject* type) { - size_t size = CType::GetSize(cx, type); + // Allocate a minimum of sizeof(ffi_arg) to handle small integers. + size_t size = Align(CType::GetSize(cx, type), sizeof(ffi_arg)); mData = new char[size]; if (mData) memset(mData, 0, size); @@ -4958,7 +4959,8 @@ FunctionType::Call(JSContext* cx, // initialize a pointer to an appropriate location, for storing the result AutoValue returnValue; - if (CType::GetTypeCode(cx, fninfo->mReturnType) != TYPE_void_t && + TypeCode typeCode = CType::GetTypeCode(cx, fninfo->mReturnType); + if (typeCode != TYPE_void_t && !returnValue.SizeToType(cx, fninfo->mReturnType)) { JS_ReportAllocationOverflow(cx); return false; @@ -4975,6 +4977,25 @@ FunctionType::Call(JSContext* cx, JS_ResumeRequest(cx, rc); + // Small integer types get returned as a word-sized ffi_arg. Coerce it back + // into the correct size for ConvertToJS. + switch (typeCode) { +#define DEFINE_INT_TYPE(name, type, ffiType) \ + case TYPE_##name: \ + if (sizeof(type) < sizeof(ffi_arg)) { \ + ffi_arg data = *static_cast(returnValue.mData); \ + *static_cast(returnValue.mData) = static_cast(data); \ + } \ + break; +#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_BOOL_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_JSCHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#include "typedefs.h" + default: + break; + } + // prepare a JS object from the result return ConvertToJS(cx, fninfo->mReturnType, NULL, returnValue.mData, false, true, rval); @@ -5216,10 +5237,6 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData) JS_ASSERT(args); JS_ASSERT(userData); - // Initialize the result to zero, in case something fails. - if (cif->rtype != &ffi_type_void) - memset(result, 0, cif->rtype->size); - // Retrieve the essentials from our closure object. ClosureInfo* cinfo = static_cast(userData); JSContext* cx = cinfo->cx; @@ -5238,6 +5255,29 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData) FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, typeObj); JS_ASSERT(cif == &fninfo->mCIF); + TypeCode typeCode = CType::GetTypeCode(cx, fninfo->mReturnType); + + // Initialize the result to zero, in case something fails. Small integer types + // are promoted to a word-sized ffi_arg, so we must be careful to zero the + // whole word. + if (cif->rtype != &ffi_type_void) { + size_t size = cif->rtype->size; + switch (typeCode) { +#define DEFINE_INT_TYPE(name, type, ffiType) \ + case TYPE_##name: +#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_BOOL_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_JSCHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#include "typedefs.h" + size = Align(size, sizeof(ffi_arg)); + break; + default: + break; + } + memset(result, 0, size); + } + // Get a death grip on 'closureObj'. js::AutoObjectRooter root(cx, cinfo->closureObj); @@ -5272,7 +5312,27 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData) // type, which would require an allocation that we can't track. The JS // function must perform this conversion itself and return a PointerType // CData; thusly, the burden of freeing the data is left to the user. - ImplicitConvert(cx, rval, fninfo->mReturnType, result, false, NULL); + if (!ImplicitConvert(cx, rval, fninfo->mReturnType, result, false, NULL)) + return; + + // Small integer types must be returned as a word-sized ffi_arg. Coerce it + // back into the size libffi expects. + switch (typeCode) { +#define DEFINE_INT_TYPE(name, type, ffiType) \ + case TYPE_##name: \ + if (sizeof(type) < sizeof(ffi_arg)) { \ + ffi_arg data = *static_cast(result); \ + *static_cast(result) = data; \ + } \ + break; +#define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_BOOL_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#define DEFINE_JSCHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z) +#include "typedefs.h" + default: + break; + } } /*******************************************************************************