Skip to content

Commit 67334c0

Browse files
committed
RTYPEDDATA_DATA: reject embedded typeddata
Callers should use the safer `RTYPEDDATA_GET_DATA`.
1 parent 9e73328 commit 67334c0

1 file changed

Lines changed: 21 additions & 2 deletions

File tree

include/ruby/internal/core/rtypeddata.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
# include <stddef.h>
2727
#endif
2828

29+
#include "ruby/assert.h"
2930
#include "ruby/internal/assume.h"
3031
#include "ruby/internal/attr/artificial.h"
3132
#include "ruby/internal/attr/flag_enum.h"
@@ -94,13 +95,15 @@
9495
*/
9596
#define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj))
9697

98+
static inline VALUE rbimpl_check_external_typeddata(VALUE obj);
99+
97100
/**
98101
* Convenient getter macro.
99102
*
100103
* @param v An object, which is in fact an ::RTypedData.
101104
* @return The passed object's ::RTypedData::data field.
102105
*/
103-
#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
106+
#define RTYPEDDATA_DATA(v) (RTYPEDDATA(rbimpl_check_external_typeddata(v))->data)
104107

105108
/** @old{rb_check_typeddata} */
106109
#define Check_TypedStruct(v, t) \
@@ -600,7 +603,7 @@ rbimpl_typeddata_get_data(VALUE obj)
600603
{
601604
/* We reuse the data pointer in embedded TypedData. */
602605
return rbimpl_typeddata_embedded_p(obj) ?
603-
RBIMPL_CAST((void *)&RTYPEDDATA_DATA(obj)) :
606+
RBIMPL_CAST((void *)&RTYPEDDATA(obj)->data) :
604607
RTYPEDDATA_DATA(obj);
605608
}
606609

@@ -736,6 +739,22 @@ rbimpl_check_typeddata(VALUE obj, const rb_data_type_t *expected_type)
736739
return RTYPEDDATA_GET_DATA(obj);
737740
}
738741

742+
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
743+
RBIMPL_ATTR_ARTIFICIAL()
744+
/**
745+
* @private
746+
*
747+
* This is an implementation detail of RTYPEDDATA_DATA(). Don't use it
748+
* directly.
749+
*/
750+
static inline VALUE
751+
rbimpl_check_external_typeddata(VALUE obj)
752+
{
753+
RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false));
754+
RUBY_ASSERT(rbimpl_obj_typeddata_p(obj));
755+
RUBY_ASSERT(!rbimpl_typeddata_embedded_p(obj));
756+
return obj;
757+
}
739758

740759
/**
741760
* Obtains a C struct from inside of a wrapper Ruby object.

0 commit comments

Comments
 (0)