[前][次][番号順一覧][スレッド一覧]

ruby-changes:55761

From: Nobuyoshi <ko1@a...>
Date: Mon, 20 May 2019 22:08:28 +0900 (JST)
Subject: [ruby-changes:55761] Nobuyoshi Nakada: e83f10b368 (trunk): Get rid of undefined behavior that source and destination buffers overlap

https://git.ruby-lang.org/ruby.git/commit/?id=e83f10b368

From e83f10b36865c7fc3f3e09deab679c4270310021 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Mon, 20 May 2019 21:58:06 +0900
Subject: Get rid of undefined behavior that source and destination buffers
 overlap


diff --git a/gc.c b/gc.c
index 7f3cc8b..6617559 100644
--- a/gc.c
+++ b/gc.c
@@ -11024,10 +11024,10 @@ method_type_name(rb_method_type_t type) https://github.com/ruby/ruby/blob/trunk/gc.c#L11024
 static void
 rb_raw_iseq_info(char *buff, const int buff_size, const rb_iseq_t *iseq)
 {
-    if (iseq->body && iseq->body->location.label && !RB_TYPE_P(iseq->body->location.pathobj, T_MOVED)) {
+    if (buff_size > 0 && iseq->body && iseq->body->location.label && !RB_TYPE_P(iseq->body->location.pathobj, T_MOVED)) {
 	VALUE path = rb_iseq_path(iseq);
 	VALUE n = iseq->body->location.first_lineno;
-	snprintf(buff, buff_size, "%s %s@%s:%d", buff,
+	snprintf(buff, buff_size, " %s@%s:%d",
 		 RSTRING_PTR(iseq->body->location.label),
 		 RSTRING_PTR(path),
 		 n ? FIX2INT(n) : 0 );
@@ -11037,14 +11037,18 @@ rb_raw_iseq_info(char *buff, const int buff_size, const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/gc.c#L11037
 const char *
 rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
 {
+    int pos = 0;
+
+#define BUFF_ARGS buff + pos, buff_size - pos
+#define APPENDF(f) if ((pos += snprintf f) >= buff_size) goto end
     if (SPECIAL_CONST_P(obj)) {
-	snprintf(buff, buff_size, "%s", obj_type_name(obj));
+	APPENDF((BUFF_ARGS, "%s", obj_type_name(obj)));
 
         if (FIXNUM_P(obj)) {
-            snprintf(buff, buff_size, "%s %ld", buff, FIX2LONG(obj));
+            APPENDF((BUFF_ARGS, " %ld", FIX2LONG(obj)));
         }
         else if (SYMBOL_P(obj)) {
-            snprintf(buff, buff_size, "%s %s", buff, rb_id2name(SYM2ID(obj)));
+            APPENDF((BUFF_ARGS, " %s", rb_id2name(SYM2ID(obj))));
         }
     }
     else {
@@ -11055,45 +11059,45 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L11059
 	const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags);
 
         if (is_pointer_to_heap(&rb_objspace, (void *)obj)) {
-            snprintf(buff, buff_size, "%p [%d%s%s%s%s%s] %s",
+            APPENDF((BUFF_ARGS, "%p [%d%s%s%s%s%s] %s",
                      (void *)obj, age,
                      C(RVALUE_UNCOLLECTIBLE_BITMAP(obj),  "L"),
                      C(RVALUE_MARK_BITMAP(obj),           "M"),
                      C(RVALUE_PIN_BITMAP(obj),            "P"),
                      C(RVALUE_MARKING_BITMAP(obj),        "R"),
                      C(RVALUE_WB_UNPROTECTED_BITMAP(obj), "U"),
-                     obj_type_name(obj));
+                     obj_type_name(obj)));
         }
         else {
             /* fake */
-            snprintf(buff, buff_size, "%p [%dXXXX] %s",
+            APPENDF((BUFF_ARGS, "%p [%dXXXX] %s",
                      (void *)obj, age,
-                     obj_type_name(obj));
+                     obj_type_name(obj)));
         }
 #else
-	snprintf(buff, buff_size, "%p [%s] %s",
+	APPENDF((BUFF_ARGS, "%p [%s] %s",
 		 (void *)obj,
 		 C(RVALUE_MARK_BITMAP(obj),           "M"),
-		 obj_type_name(obj));
+		 obj_type_name(obj)));
 #endif
 
 	if (internal_object_p(obj)) {
 	    /* ignore */
 	}
 	else if (RBASIC(obj)->klass == 0) {
-	    snprintf(buff, buff_size, "%s (temporary internal)", buff);
+	    APPENDF((BUFF_ARGS, "(temporary internal)"));
 	}
 	else {
             if (RTEST(RBASIC(obj)->klass)) {
 	    VALUE class_path = rb_class_path_cached(RBASIC(obj)->klass);
 	    if (!NIL_P(class_path)) {
-		snprintf(buff, buff_size, "%s (%s)", buff, RSTRING_PTR(class_path));
+		APPENDF((BUFF_ARGS, "(%s)", RSTRING_PTR(class_path)));
 	    }
             }
 	}
 
 #if GC_DEBUG
-	snprintf(buff, buff_size, "%s @%s:%d", buff, RANY(obj)->file, RANY(obj)->line);
+	APPENDF((BUFF_ARGS, "@%s:%d", RANY(obj)->file, RANY(obj)->line));
 #endif
 
 	switch (type) {
@@ -11102,38 +11106,38 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L11106
 	    break;
 	  case T_ARRAY:
             if (FL_TEST(obj, ELTS_SHARED)) {
-                snprintf(buff, buff_size, "%s shared -> %s", buff,
-                         rb_obj_info(RARRAY(obj)->as.heap.aux.shared));
+                APPENDF((BUFF_ARGS, "shared -> %s",
+                         rb_obj_info(RARRAY(obj)->as.heap.aux.shared)));
             }
             else if (FL_TEST(obj, RARRAY_EMBED_FLAG)) {
-                snprintf(buff, buff_size, "%s [%s%s] len: %d (embed)", buff,
+                APPENDF((BUFF_ARGS, "[%s%s] len: %d (embed)",
                          C(ARY_EMBED_P(obj),  "E"),
                          C(ARY_SHARED_P(obj), "S"),
-                         (int)RARRAY_LEN(obj));
+                         (int)RARRAY_LEN(obj)));
             }
             else {
-                snprintf(buff, buff_size, "%s [%s%s%s] len: %d, capa:%d ptr:%p", buff,
+                APPENDF((BUFF_ARGS, "[%s%s%s] len: %d, capa:%d ptr:%p",
                          C(ARY_EMBED_P(obj),  "E"),
                          C(ARY_SHARED_P(obj), "S"),
                          C(RARRAY_TRANSIENT_P(obj), "T"),
                          (int)RARRAY_LEN(obj),
                          ARY_EMBED_P(obj) ? -1 : (int)RARRAY(obj)->as.heap.aux.capa,
-                         (void *)RARRAY_CONST_PTR_TRANSIENT(obj));
+                         (void *)RARRAY_CONST_PTR_TRANSIENT(obj)));
             }
 	    break;
 	  case T_STRING: {
-	    snprintf(buff, buff_size, "%s %s", buff, RSTRING_PTR(obj));
+	    APPENDF((BUFF_ARGS, "%s", RSTRING_PTR(obj)));
 	    break;
 	  }
           case T_MOVED: {
-            snprintf(buff, buff_size, "-> %p", (void*)rb_gc_location(obj));
+            APPENDF((BUFF_ARGS, "-> %p", (void*)rb_gc_location(obj)));
             break;
           }
           case T_HASH: {
-              snprintf(buff, buff_size, "%s [%c%c] %d", buff,
+              APPENDF((BUFF_ARGS, "[%c%c] %d",
                        RHASH_AR_TABLE_P(obj) ? 'A' : 'S',
                        RHASH_TRANSIENT_P(obj) ? 'T' : ' ',
-                       (int)RHASH_SIZE(obj));
+                       (int)RHASH_SIZE(obj)));
               break;
           }
           case T_CLASS:
@@ -11141,7 +11145,7 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L11145
             {
                 VALUE class_path = rb_class_path_cached(obj);
                 if (!NIL_P(class_path)) {
-                    snprintf(buff, buff_size, "%s %s", buff, RSTRING_PTR(class_path));
+                    APPENDF((BUFF_ARGS, "%s", RSTRING_PTR(class_path)));
                 }
                 break;
             }
@@ -11149,7 +11153,7 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L11153
             {
                 VALUE class_path = rb_class_path_cached(RBASIC_CLASS(obj));
                 if (!NIL_P(class_path)) {
-                    snprintf(buff, buff_size, "%s src:%s", buff, RSTRING_PTR(class_path));
+                    APPENDF((BUFF_ARGS, "src:%s", RSTRING_PTR(class_path)));
                 }
                 break;
             }
@@ -11158,11 +11162,11 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L11162
                 uint32_t len = ROBJECT_NUMIV(obj);
 
                 if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
-                    snprintf(buff, buff_size, "%s (embed) len:%d", buff, len);
+                    APPENDF((BUFF_ARGS, "(embed) len:%d", len));
                 }
                 else {
                     VALUE *ptr = ROBJECT_IVPTR(obj);
-                    snprintf(buff, buff_size, "%s len:%d ptr:%p", buff, len, (void *)ptr);
+                    APPENDF((BUFF_ARGS, "len:%d ptr:%p", len, (void *)ptr));
                 }
             }
             break;
@@ -11173,12 +11177,12 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L11177
 		(block = vm_proc_block(obj)) != NULL &&
 		(vm_block_type(block) == block_type_iseq) &&
 		(iseq = vm_block_iseq(block)) != NULL) {
-		rb_raw_iseq_info(buff, buff_size, iseq);
+		rb_raw_iseq_info(BUFF_ARGS, iseq);
 	    }
 	    else {
 		const char * const type_name = rb_objspace_data_type_name(obj);
 		if (type_name) {
-		    snprintf(buff, buff_size, "%s %s", buff, type_name);
+		    APPENDF((BUFF_ARGS, "%s", type_name));
 		}
 	    }
 	    break;
@@ -11201,27 +11205,27 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L11205
 #undef IMEMO_NAME
 	      default: UNREACHABLE;
 	    }
-	    snprintf(buff, buff_size, "%s %s", buff, imemo_name);
+	    APPENDF((BUFF_ARGS, "%s", imemo_name));
 
 	    switch (imemo_type(obj)) {
 	      case imemo_ment: {
 		const rb_method_entry_t *me = &RANY(obj)->as.imemo.ment;
 		if (me->def) {
-		    snprintf(buff, buff_size, "%s (called_id: %s, type: %s, alias: %d, owner: %s, defined_class: %s)", buff,
+		    APPENDF((BUFF_ARGS, "(called_id: %s, type: %s, alias: %d, owner: %s, defined_class: %s)",
 			     rb_id2name(me->called_id),
 			     method_type_name(me->def->type),
 			     me->def->alias_count,
 			     obj_info(me->owner),
-			     obj_info(me->defined_class));
+			     obj_info(me->defined_class)));
 		}
 		else {
-		    snprintf(buff, buff_size, "%s", rb_id2name(me->called_id));
+		    APPENDF((BUFF_ARGS, "%s", rb_id2name(me->called_id)));
 		}
 		break;
 	      }
 	      case imemo_iseq: {
 		const rb_iseq_t *iseq = (const rb_iseq_t *)obj;
-		rb_raw_iseq_info(buff, buff_size, iseq);
+		rb_raw_iseq_info(BUFF_ARGS, iseq);
 		break;
 	      }
 	      default:
@@ -11234,7 +11238,10 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L11238
 #undef TF
 #undef C
     }
+  en (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]