@@ -119,6 +119,7 @@ typedef union {
119119#define MAX_INTEGER_PACK_SIZE 8
120120
121121static const char toofew [] = "too few arguments" ;
122+ static const char intoitself [] = "cannot pack buffer object into itself" ;
122123
123124static void encodes (VALUE ,const char * ,long ,int ,int );
124125static void qpencode (VALUE ,VALUE ,long );
@@ -280,6 +281,8 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
280281#define MORE_ITEM (idx < RARRAY_LEN(ary))
281282#define THISFROM (MORE_ITEM ? RARRAY_AREF(ary, idx) : TOO_FEW)
282283#define NEXTFROM (MORE_ITEM ? RARRAY_AREF(ary, idx++) : TOO_FEW)
284+ #define NOT_BUFFER (val ) (((val) == res) ? rb_raise(rb_eArgError, intoitself) : (void)0)
285+ #define STR_FROM (val ) NOT_BUFFER(StringValue(val))
283286
284287 while (p < pend ) {
285288 int explicit_endian = 0 ;
@@ -334,7 +337,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
334337 plen = 0 ;
335338 }
336339 else {
337- StringValue (from );
340+ STR_FROM (from );
338341 ptr = RSTRING_PTR (from );
339342 plen = RSTRING_LEN (from );
340343 }
@@ -719,7 +722,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
719722 case 'u' : /* uuencoded string */
720723 case 'm' : /* base64 encoded string */
721724 from = NEXTFROM ;
722- StringValue (from );
725+ STR_FROM (from );
723726 ptr = RSTRING_PTR (from );
724727 plen = RSTRING_LEN (from );
725728
@@ -749,6 +752,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
749752
750753 case 'M' : /* quoted-printable encoded string */
751754 from = rb_obj_as_string (NEXTFROM );
755+ NOT_BUFFER (from );
752756 if (len <= 1 )
753757 len = 72 ;
754758 qpencode (res , from , len );
@@ -757,7 +761,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
757761 case 'P' : /* pointer to packed byte string */
758762 from = THISFROM ;
759763 if (!NIL_P (from )) {
760- StringValue (from );
764+ STR_FROM (from );
761765 if (RSTRING_LEN (from ) < len ) {
762766 rb_raise (rb_eArgError , "too short buffer for P(%ld for %ld)" ,
763767 RSTRING_LEN (from ), len );
@@ -767,13 +771,11 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
767771 /* FALL THROUGH */
768772 case 'p' : /* pointer to string */
769773 while (len -- > 0 ) {
770- char * t ;
774+ char * t = 0 ;
771775 from = NEXTFROM ;
772- if (NIL_P (from )) {
773- t = 0 ;
774- }
775- else {
776- t = StringValuePtr (from );
776+ if (!NIL_P (from )) {
777+ STR_FROM (from );
778+ t = RSTRING_PTR (from );
777779 }
778780 if (!associates ) {
779781 associates = rb_ary_new ();
0 commit comments