|
1 | 1 | #include "ArgConverter.h" |
2 | 2 | #include <Foundation/Foundation.h> |
| 3 | +#include <algorithm> |
3 | 4 | #include <sstream> |
4 | 5 | #include "DictionaryAdapter.h" |
5 | 6 | #include "Helpers.h" |
|
434 | 435 | if (!success) { |
435 | 436 | memset(retValue, 0, cif->rtype->size); |
436 | 437 | } else { |
437 | | - ArgConverter::SetValue(context, retValue, result, data->typeEncoding_); |
| 438 | + ArgConverter::SetValue(context, retValue, cif->rtype->size, result, data->typeEncoding_); |
438 | 439 | } |
439 | 440 | } else { |
440 | 441 | memset(retValue, 0, cif->rtype->size); |
|
446 | 447 | } |
447 | 448 | } |
448 | 449 |
|
449 | | -void ArgConverter::SetValue(Local<Context> context, void* retValue, Local<Value> value, |
450 | | - const TypeEncoding* typeEncoding) { |
| 450 | +void ArgConverter::SetValue(Local<Context> context, void* retValue, size_t returnSize, |
| 451 | + Local<Value> value, const TypeEncoding* typeEncoding) { |
451 | 452 | if (typeEncoding->type == BinaryTypeEncodingType::VoidEncoding) { |
452 | 453 | return; |
453 | 454 | } |
454 | 455 |
|
455 | 456 | // Runs inside an ffi closure, where a C++ throw cannot propagate; a revoked |
456 | | - // proxy returns nil. |
| 457 | + // proxy returns nil. libffi sizes the return slot to at least ffi_arg even |
| 458 | + // for narrower types, and the full slot must be written. |
457 | 459 | value = tns::UnwrapProxy(value); |
458 | 460 | if (value.IsEmpty() || value->IsNullOrUndefined()) { |
459 | | - void* nullPtr = nullptr; |
460 | | - *(ffi_arg*)retValue = (unsigned long)nullPtr; |
| 461 | + memset(retValue, 0, std::max(returnSize, sizeof(ffi_arg))); |
461 | 462 | return; |
462 | 463 | } |
463 | 464 |
|
|
0 commit comments