String#inspect may raise Exception

e$B@.@%$G$9!#e(B

["\x82\xa0".force_encoding(“sjis”),
“\xa4\xa2”.force_encoding(“euc-jp”),
“\xe3\x81\x82”.force_encoding(“utf-8”)].inspect
ArgumentError: append incompatible encoding strings: Shift_JIS and
EUC-JP

e$B$H$J$j$^$9!#e(B

e$B;W$&$K!“8=:_e(B String#inspect e$B$O<+J,<+?H$Ne(B encoding
e$B$HCf?H$N%P%$%HNs$rHf3Se(B
e$B$7$Fe(B valid
e$B$J$i$P%(%9%1!<%W$7$J$$$H$$$&=hM}$r9T$C$F$$$^$9$,!”<+J,<+?H$Ne(B
encoding e$B$G$J$/!“7k2L$H$J$kJ8;zNs$Ne(B encoding
e$B$r4p=`$H$9$kI,MW$,$”$k$H;We(B
e$B$o$l$^$9!#e(B

e$B$D$^$k$H$3$m!“e(Binspect e$B$,0z?t$Ke(B encoding
e$B$r<h$kI,MW$,$”$k$N$G$9$,!“e(B
inspect e$B$O:F5"E*$K8F$P$l$k$?$a!”%f!<%6!<%%V%8%’%/%H$G$be(B
inspect(enc) e$B$,e(B
e$BDj5A$5$l$F$$$kI,MW$,$"$j!"7k2LE
$K$3$N%"%W%m!<%A$O;veIT2DG=$G$9!#e(B

e$B?7;EMMBP1~$Ne(B inspect e$B$,%9%l%C%I%m!<%+%kJQ?t$K4|BT$9$ke(B
encoding e$B$r%;%C%He(B
e$B$9$k$H$$$&5;$b$J$-$K$7$b$"$i$:$G$9$,!“8=:_$N%^%k%A%P%$%HJ8;zNs$r%(%9%1!<e(B
e$B%W$J$7$K=PNO$9$k$H$$$&;EMM$r$”$-$i$a$6$k$r$($J$$$h$&$K46$8$^$9!#e(B

e$B$J$*!“e(BString#inspect e$B$K8B$C$F!“0z?t$H$7$Fe(B encoding
e$B$r<h$k!”$H$$$&$N$J$ie(B
e$B$P!”$=$l$O$$$^$@2DG=$G$O$"$j$^$9!#e(B

— string.c (revision 15383)
+++ string.c (local)
@@ -3259,23 +3259,6 @@
return str;
}

-static void
-str_cat_char(VALUE str, int c, rb_encoding *enc)
-{

  • char s[16];
  • int n = rb_enc_codelen(c, enc);
  • rb_enc_mbcput(c, s, enc);
  • rb_enc_str_buf_cat(str, s, n, enc);
    -}

-static void
-prefix_escape(VALUE str, int c, rb_encoding *enc)
-{

  • str_cat_char(str, ‘\’, enc);
  • str_cat_char(str, c, enc);
    -}

/*

  • call-seq:
  • str.inspect => string
    @@ -3291,81 +3274,65 @@
    VALUE
    rb_str_inspect(VALUE str)
    {
  • rb_encoding *enc = STR_ENC_GET(str);
    char *p, *pend;
  • VALUE result = rb_str_buf_new2("");
  • VALUE result = rb_str_buf_new2(""");
  • rb_enc_associate(result, enc);
  • str_cat_char(result, ‘"’, enc);
  • ENCODING_CODERANGE_SET(result, rb_usascii_encindex(),
    ENC_CODERANGE_7BIT);
    p = RSTRING_PTR(str); pend = RSTRING_END(str);
    while (p < pend) {
  •   int c;
    
  •   int n;
    
  •   int c = *p++;
      int cc;
    
  •    n = rb_enc_precise_mbclen(p, pend, enc);
    
  •    if (!MBCLEN_CHARFOUND_P(n)) {
    
  •        p++;
    
  •        n = 1;
    
  •        goto escape_codepoint;
    
  •    }
    
  •    n = MBCLEN_CHARFOUND_LEN(n);
    
  •   c = rb_enc_codepoint(p, pend, enc);
    
  •   n = rb_enc_codelen(c, enc);
    
  •   p += n;
    
  •   if (c == '"'|| c == '\\' ||
    
  •       (c == '#' &&
    
  •   if (c == '#' &&
            p < pend &&
    
  •         MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
    
  •         (cc = rb_enc_codepoint(p,pend,enc),
    
  •          (cc == '$' || cc == '@' || cc == '{')))) {
    
  •       prefix_escape(result, c, enc);
    
  •         (cc = *(p),
    
  •          (cc == '$' || cc == '@' || cc == '{'))) {
    
  •       rb_str_buf_cat2(result, "\\#");
      }
    
  •    else if (c == '"') {
    
  •       rb_str_buf_cat2(result, "\\\"");
    
  •    }
    
  •    else if (c == '\\') {
    
  •       rb_str_buf_cat2(result, "\\\\");
    
  •    }
      else if (c == '\n') {
    
  •       prefix_escape(result, 'n', enc);
    
  •       rb_str_buf_cat2(result, "\\n");
      }
      else if (c == '\r') {
    
  •       prefix_escape(result, 'r', enc);
    
  •       rb_str_buf_cat2(result, "\\r");
      }
      else if (c == '\t') {
    
  •       prefix_escape(result, 't', enc);
    
  •       rb_str_buf_cat2(result, "\\t");
      }
      else if (c == '\f') {
    
  •       prefix_escape(result, 'f', enc);
    
  •       rb_str_buf_cat2(result, "\\f");
      }
      else if (c == '\013') {
    
  •       prefix_escape(result, 'v', enc);
    
  •       rb_str_buf_cat2(result, "\\v");
      }
      else if (c == '\010') {
    
  •       prefix_escape(result, 'b', enc);
    
  •       rb_str_buf_cat2(result, "\\b");
      }
      else if (c == '\007') {
    
  •       prefix_escape(result, 'a', enc);
    
  •       rb_str_buf_cat2(result, "\\a");
      }
      else if (c == 033) {
    
  •       prefix_escape(result, 'e', enc);
    
  •       rb_str_buf_cat2(result, "\\e");
      }
    
  •   else if (rb_enc_isprint(c, enc)) {
    
  •       rb_enc_str_buf_cat(result, p-n, n, enc);
    
  •   }
      else {
          char buf[5];
          char *s;
           char *q;
    
        escape_codepoint:
    
  •        for (q = p-n; q < p; q++) {
    
  •        for (q = p-1; q < p; q++) {
               s = buf;
               sprintf(buf, "\\x%02X", *q & 0377);
    
  •            while (*s) {
    
  •                str_cat_char(result, *s++, enc);
    
  •            }
    
  •            rb_str_buf_cat2(result, s);
           }
      }
    
    }
  • str_cat_char(result, ‘"’, enc);
  • rb_str_buf_cat2(result, “”");

    OBJ_INFECT(result, str);
    return result;