|
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" |
|
438 | 439 | if (!success) { |
439 | 440 | memset(retValue, 0, cif->rtype->size); |
440 | 441 | } else { |
441 | | - ArgConverter::SetValue(context, retValue, result, data->typeEncoding_); |
| 442 | + ArgConverter::SetValue(context, retValue, cif->rtype->size, result, data->typeEncoding_); |
442 | 443 | } |
443 | 444 | } else { |
444 | 445 | memset(retValue, 0, cif->rtype->size); |
|
450 | 451 | } |
451 | 452 | } |
452 | 453 |
|
453 | | -void ArgConverter::SetValue(Local<Context> context, void* retValue, Local<Value> value, |
454 | | - const TypeEncoding* typeEncoding) { |
| 454 | +void ArgConverter::SetValue(Local<Context> context, void* retValue, size_t returnSize, |
| 455 | + Local<Value> value, const TypeEncoding* typeEncoding) { |
455 | 456 | if (typeEncoding->type == BinaryTypeEncodingType::VoidEncoding) { |
456 | 457 | return; |
457 | 458 | } |
458 | 459 |
|
459 | 460 | // Runs inside an ffi closure, where a C++ throw cannot propagate; a revoked |
460 | | - // proxy returns nil. |
| 461 | + // proxy returns nil. libffi sizes the return slot to at least ffi_arg even |
| 462 | + // for narrower types, and the full slot must be written. |
461 | 463 | value = tns::UnwrapProxy(value); |
462 | 464 | if (value.IsEmpty() || value->IsNullOrUndefined()) { |
463 | | - void* nullPtr = nullptr; |
464 | | - *(ffi_arg*)retValue = (unsigned long)nullPtr; |
| 465 | + memset(retValue, 0, std::max(returnSize, sizeof(ffi_arg))); |
465 | 466 | return; |
466 | 467 | } |
467 | 468 |
|
|
0 commit comments