mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-10 00:00:50 +00:00
Fix leaked FFI structure argument/returntype information
This commit is contained in:
parent
2f9f0d6761
commit
bdad4987ae
6 changed files with 79 additions and 59 deletions
|
@ -295,8 +295,7 @@ exitedThread(void *slot)
|
||||||
_sig = RETAIN(aSignature);
|
_sig = RETAIN(aSignature);
|
||||||
_numArgs = [aSignature numberOfArguments];
|
_numArgs = [aSignature numberOfArguments];
|
||||||
_info = [aSignature methodInfo];
|
_info = [aSignature methodInfo];
|
||||||
_frame = cifframe_from_signature(_sig);
|
[self setupFrameFFI: _sig];
|
||||||
[_frame retain];
|
|
||||||
_cframe = [_frame mutableBytes];
|
_cframe = [_frame mutableBytes];
|
||||||
|
|
||||||
/* Make sure we have somewhere to store the return value if needed.
|
/* Make sure we have somewhere to store the return value if needed.
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#import "Foundation/NSInvocation.h"
|
#import "Foundation/NSInvocation.h"
|
||||||
|
|
||||||
@class NSMutableData;
|
@class NSMutableData;
|
||||||
|
@class NSPointerArray;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int offset;
|
int offset;
|
||||||
|
@ -42,10 +43,14 @@ typedef struct {
|
||||||
@interface GSFFIInvocation : NSInvocation
|
@interface GSFFIInvocation : NSInvocation
|
||||||
{
|
{
|
||||||
@public
|
@public
|
||||||
uint8_t _retbuf[32]; // Store return values of up to 32 bytes here.
|
uint8_t _retbuf[32]; // Return values of up to 32 bytes here.
|
||||||
NSMutableData *_frame;
|
NSMutableData *_frame; // Frame information for invoking.
|
||||||
|
NSPointerArray *_extra; // Extra FFI data to be released.
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
@interface GSFFIInvocation (FFI)
|
||||||
|
- (void) setupFrameFFI: (NSMethodSignature*)sig;
|
||||||
|
@end
|
||||||
|
|
||||||
@interface GSFFCallInvocation : NSInvocation
|
@interface GSFFCallInvocation : NSInvocation
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
@class _GSMutableInsensitiveDictionary;
|
@class _GSMutableInsensitiveDictionary;
|
||||||
|
|
||||||
@class NSNotification;
|
@class NSNotification;
|
||||||
|
@class NSPointerArray;
|
||||||
@class NSRecursiveLock;
|
@class NSRecursiveLock;
|
||||||
|
|
||||||
#if ( (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) ) && HAVE_VISIBILITY_ATTRIBUTE )
|
#if ( (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) ) && HAVE_VISIBILITY_ATTRIBUTE )
|
||||||
|
@ -559,13 +560,14 @@ GSPrivateUnloadModule(FILE *errorStream,
|
||||||
void *buffer;
|
void *buffer;
|
||||||
void *executable;
|
void *executable;
|
||||||
id frame;
|
id frame;
|
||||||
|
NSPointerArray *extra;
|
||||||
}
|
}
|
||||||
+ (GSCodeBuffer*) memoryWithSize: (NSUInteger)_size;
|
+ (GSCodeBuffer*) memoryWithSize: (NSUInteger)_size;
|
||||||
- (void*) buffer;
|
- (void*) buffer;
|
||||||
- (void*) executable;
|
- (void*) executable;
|
||||||
- (id) initWithSize: (NSUInteger)_size;
|
- (id) initWithSize: (NSUInteger)_size;
|
||||||
- (void) protect;
|
- (void) protect;
|
||||||
- (void) setFrame: (id)aFrame;
|
- (void) setFrame: (id)aFrame extra: (NSPointerArray*)pa;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/* For tuning socket connections
|
/* For tuning socket connections
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
DESTROY(frame);
|
DESTROY(frame);
|
||||||
|
DESTROY(extra);
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_FFI_PREP_CLOSURE_LOC)
|
#if defined(HAVE_FFI_PREP_CLOSURE_LOC)
|
||||||
|
@ -173,9 +174,10 @@
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setFrame: (id)aFrame
|
- (void) setFrame: (id)aFrame extra: (NSPointerArray*)pa
|
||||||
{
|
{
|
||||||
ASSIGN(frame, aFrame);
|
ASSIGN(frame, aFrame);
|
||||||
|
ASSIGN(extra, pa);
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -52,16 +52,14 @@ typedef struct _cifframe_t {
|
||||||
|
|
||||||
@class NSMutableData;
|
@class NSMutableData;
|
||||||
|
|
||||||
extern NSMutableData *cifframe_from_signature (NSMethodSignature *info);
|
extern GSCodeBuffer* cifframe_closure(NSMethodSignature *sig, void (*func)());
|
||||||
|
|
||||||
extern GSCodeBuffer* cifframe_closure (NSMethodSignature *sig, void (*func)());
|
|
||||||
|
|
||||||
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer,
|
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer,
|
||||||
int size);
|
int size);
|
||||||
extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer,
|
extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer,
|
||||||
int size);
|
int size);
|
||||||
extern void *cifframe_arg_addr(cifframe_t *cframe, int index);
|
extern void *cifframe_arg_addr(cifframe_t *cframe, int index);
|
||||||
extern BOOL cifframe_decode_arg (const char *type, void* buffer);
|
extern BOOL cifframe_decode_arg(const char *type, void* buffer);
|
||||||
extern BOOL cifframe_encode_arg (const char *type, void* buffer);
|
extern BOOL cifframe_encode_arg(const char *type, void* buffer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cifframe.h"
|
#include "cifframe.h"
|
||||||
|
#import "Foundation/NSPointerArray.h"
|
||||||
#import "Foundation/NSException.h"
|
#import "Foundation/NSException.h"
|
||||||
#import "Foundation/NSData.h"
|
#import "Foundation/NSData.h"
|
||||||
#import "GSInvocation.h"
|
#import "GSInvocation.h"
|
||||||
|
@ -91,7 +92,8 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ffi_type *cifframe_type(const char *typePtr, const char **advance);
|
static ffi_type *
|
||||||
|
cifframe_type(const char *typePtr, const char **adv, NSPointerArray **extra);
|
||||||
|
|
||||||
/* Best guess at the space needed for a structure, since we don't know
|
/* Best guess at the space needed for a structure, since we don't know
|
||||||
for sure until it's calculated in ffi_prep_cif, which is too late */
|
for sure until it's calculated in ffi_prep_cif, which is too late */
|
||||||
|
@ -122,9 +124,9 @@ cifframe_guess_struct_size(ffi_type *stype)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
NSMutableData *
|
cifframe_from_signature(NSMethodSignature *info,
|
||||||
cifframe_from_signature (NSMethodSignature *info)
|
NSMutableData **frame, NSPointerArray **extra)
|
||||||
{
|
{
|
||||||
unsigned size = sizeof(cifframe_t);
|
unsigned size = sizeof(cifframe_t);
|
||||||
unsigned align = __alignof(double);
|
unsigned align = __alignof(double);
|
||||||
|
@ -138,14 +140,14 @@ cifframe_from_signature (NSMethodSignature *info)
|
||||||
ffi_type *arg_types[numargs];
|
ffi_type *arg_types[numargs];
|
||||||
cifframe_t *cframe;
|
cifframe_t *cframe;
|
||||||
|
|
||||||
/* FIXME: in cifframe_type, return values/arguments that are structures
|
/* The extra parameter returns an array of any allocated memory which
|
||||||
have custom ffi_types with are allocated separately. We should allocate
|
* needs freeing at the end of the invocation.
|
||||||
them in our cifframe so we don't leak memory. Or maybe we could
|
*/
|
||||||
cache structure types? */
|
rtype = cifframe_type([info methodReturnType], NULL, extra);
|
||||||
rtype = cifframe_type([info methodReturnType], NULL);
|
|
||||||
for (i = 0; i < numargs; i++)
|
for (i = 0; i < numargs; i++)
|
||||||
{
|
{
|
||||||
arg_types[i] = cifframe_type([info getArgumentTypeAtIndex: i], NULL);
|
arg_types[i]
|
||||||
|
= cifframe_type([info getArgumentTypeAtIndex: i], NULL, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numargs > 0)
|
if (numargs > 0)
|
||||||
|
@ -220,9 +222,21 @@ cifframe_from_signature (NSMethodSignature *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
*frame = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@implementation GSFFIInvocation (FFI)
|
||||||
|
- (void) setupFrameFFI: (NSMethodSignature*)info
|
||||||
|
{
|
||||||
|
NSMutableData *f = nil;
|
||||||
|
NSPointerArray *e = nil;
|
||||||
|
|
||||||
|
cifframe_from_signature(info, &f, &e);
|
||||||
|
ASSIGN(_frame, f);
|
||||||
|
ASSIGN(_extra, e);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
void
|
void
|
||||||
cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size)
|
cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size)
|
||||||
{
|
{
|
||||||
|
@ -250,8 +264,8 @@ cifframe_arg_addr(cifframe_t *cframe, int index)
|
||||||
/*
|
/*
|
||||||
* Get the ffi_type for this type
|
* Get the ffi_type for this type
|
||||||
*/
|
*/
|
||||||
ffi_type *
|
static ffi_type *
|
||||||
cifframe_type(const char *typePtr, const char **advance)
|
cifframe_type(const char *typePtr, const char **advance, NSPointerArray **extra)
|
||||||
{
|
{
|
||||||
static ffi_type stypeNSPoint = { 0 };
|
static ffi_type stypeNSPoint = { 0 };
|
||||||
static ffi_type stypeNSRange = { 0 };
|
static ffi_type stypeNSRange = { 0 };
|
||||||
|
@ -309,7 +323,7 @@ cifframe_type(const char *typePtr, const char **advance)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char *adv;
|
const char *adv;
|
||||||
cifframe_type(typePtr, &adv);
|
cifframe_type(typePtr, &adv, extra);
|
||||||
typePtr = adv;
|
typePtr = adv;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -328,7 +342,7 @@ cifframe_type(const char *typePtr, const char **advance)
|
||||||
{
|
{
|
||||||
typePtr++;
|
typePtr++;
|
||||||
}
|
}
|
||||||
cifframe_type(typePtr, &adv);
|
cifframe_type(typePtr, &adv, extra);
|
||||||
typePtr = adv;
|
typePtr = adv;
|
||||||
typePtr++; /* Skip end-of-array */
|
typePtr++; /* Skip end-of-array */
|
||||||
}
|
}
|
||||||
|
@ -433,8 +447,8 @@ cifframe_type(const char *typePtr, const char **advance)
|
||||||
/* An NSRect is an NSPoint and an NSSize, but those
|
/* An NSRect is an NSPoint and an NSSize, but those
|
||||||
* two structures are actually identical.
|
* two structures are actually identical.
|
||||||
*/
|
*/
|
||||||
elems[0] = cifframe_type(@encode(NSSize), NULL);
|
elems[0] = cifframe_type(@encode(NSSize), NULL, extra);
|
||||||
elems[1] = cifframe_type(@encode(NSPoint), NULL);
|
elems[1] = cifframe_type(@encode(NSPoint), NULL, extra);
|
||||||
elems[2] = 0;
|
elems[2] = 0;
|
||||||
ftype->elements = elems;
|
ftype->elements = elems;
|
||||||
ftype->type = FFI_TYPE_STRUCT;
|
ftype->type = FFI_TYPE_STRUCT;
|
||||||
|
@ -471,7 +485,7 @@ cifframe_type(const char *typePtr, const char **advance)
|
||||||
*/
|
*/
|
||||||
while (*typePtr != _C_STRUCT_E)
|
while (*typePtr != _C_STRUCT_E)
|
||||||
{
|
{
|
||||||
local = cifframe_type(typePtr, &adv);
|
local = cifframe_type(typePtr, &adv, extra);
|
||||||
typePtr = adv;
|
typePtr = adv;
|
||||||
NSCAssert(typePtr, @"End of signature while parsing");
|
NSCAssert(typePtr, @"End of signature while parsing");
|
||||||
ftype->elements[types++] = local;
|
ftype->elements[types++] = local;
|
||||||
|
@ -485,6 +499,13 @@ cifframe_type(const char *typePtr, const char **advance)
|
||||||
}
|
}
|
||||||
ftype->elements[types] = NULL;
|
ftype->elements[types] = NULL;
|
||||||
typePtr++; /* Skip end-of-struct */
|
typePtr++; /* Skip end-of-struct */
|
||||||
|
if (nil == *extra)
|
||||||
|
{
|
||||||
|
*extra = [NSPointerArray pointerArrayWithOptions:
|
||||||
|
NSPointerFunctionsOpaquePersonality
|
||||||
|
| NSPointerFunctionsMallocMemory];
|
||||||
|
}
|
||||||
|
[*extra addPointer: ftype];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -508,19 +529,11 @@ cifframe_type(const char *typePtr, const char **advance)
|
||||||
{
|
{
|
||||||
ffi_type *local;
|
ffi_type *local;
|
||||||
int align = objc_alignof_type(typePtr);
|
int align = objc_alignof_type(typePtr);
|
||||||
local = cifframe_type(typePtr, &adv);
|
local = cifframe_type(typePtr, &adv, extra);
|
||||||
typePtr = adv;
|
typePtr = adv;
|
||||||
NSCAssert(typePtr, @"End of signature while parsing");
|
NSCAssert(typePtr, @"End of signature while parsing");
|
||||||
if (align > max_align)
|
if (align > max_align)
|
||||||
{
|
{
|
||||||
if (ftype && ftype->type == FFI_TYPE_STRUCT
|
|
||||||
&& ftype != &stypeNSPoint
|
|
||||||
&& ftype != &stypeNSRange
|
|
||||||
&& ftype != &stypeNSRect
|
|
||||||
&& ftype != &stypeNSSize)
|
|
||||||
{
|
|
||||||
free(ftype);
|
|
||||||
}
|
|
||||||
ftype = local;
|
ftype = local;
|
||||||
max_align = align;
|
max_align = align;
|
||||||
}
|
}
|
||||||
|
@ -557,21 +570,22 @@ cifframe_type(const char *typePtr, const char **advance)
|
||||||
}
|
}
|
||||||
|
|
||||||
GSCodeBuffer*
|
GSCodeBuffer*
|
||||||
cifframe_closure (NSMethodSignature *sig, void (*cb)())
|
cifframe_closure(NSMethodSignature *sig, void (*cb)())
|
||||||
{
|
{
|
||||||
NSMutableData *frame;
|
NSMutableData *frame = nil;
|
||||||
|
NSPointerArray *extra = nil;
|
||||||
cifframe_t *cframe;
|
cifframe_t *cframe;
|
||||||
ffi_closure *cclosure;
|
ffi_closure *cclosure;
|
||||||
void *executable;
|
void *executable;
|
||||||
GSCodeBuffer *memory;
|
GSCodeBuffer *memory;
|
||||||
|
|
||||||
/* Construct the frame (stored in an NSMutableDate object) and sety it
|
/* Construct the frame (stored in an NSMutableDate object) and set it
|
||||||
* in a new closure.
|
* in a new closure.
|
||||||
*/
|
*/
|
||||||
frame = cifframe_from_signature(sig);
|
cifframe_from_signature(sig, &frame, &extra);
|
||||||
cframe = [frame mutableBytes];
|
cframe = [frame mutableBytes];
|
||||||
memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)];
|
memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)];
|
||||||
[memory setFrame: frame];
|
[memory setFrame: frame extra: extra];
|
||||||
cclosure = [memory buffer];
|
cclosure = [memory buffer];
|
||||||
executable = [memory executable];
|
executable = [memory executable];
|
||||||
if (cframe == NULL || cclosure == NULL)
|
if (cframe == NULL || cclosure == NULL)
|
||||||
|
|
Loading…
Reference in a new issue