The assert()ions in sv_chop() that the passed in pointer is within the
Nicholas Clark [Sun, 13 Jul 2008 20:22:25 +0000 (20:22 +0000)]
SV's buffer should be full-on panics, as bogus values passed in can
cause later heap corruption, which is a bad thing (TM).

p4raw-id: //depot/perl@34138

pod/perldiag.pod
sv.c

index f5c61d7..c512559 100644 (file)
@@ -3189,6 +3189,11 @@ then discovered it wasn't a subroutine or eval context.
 
 (P) scan_num() got called on something that wasn't a number.
 
+=item panic: sv_chop %s
+
+(P) The sv_chop() routine was passed a position that is not within the
+scalar's string buffer.
+
 =item panic: sv_insert
 
 (P) The sv_insert() routine was told to remove more string than there
diff --git a/sv.c b/sv.c
index cdae779..c2b4171 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -4389,6 +4389,7 @@ Perl_sv_chop(pTHX_ register SV *const sv, register const char *const ptr)
 #ifdef DEBUGGING
     const U8 *real_start;
 #endif
+    STRLEN max_delta;
 
     PERL_ARGS_ASSERT_SV_CHOP;
 
@@ -4399,12 +4400,17 @@ Perl_sv_chop(pTHX_ register SV *const sv, register const char *const ptr)
        /* Nothing to do.  */
        return;
     }
-    assert(ptr > SvPVX_const(sv));
+    /* SvPVX(sv) may move in SV_CHECK_THINKFIRST(sv), but after this line,
+       nothing uses the value of ptr any more.  */
+    if (ptr <= SvPVX_const(sv))
+       Perl_croak(aTHX_ "panic: sv_chop ptr=%p, start=%p, end=%p",
+                  ptr, SvPVX_const(sv), SvPVX_const(sv) + max_delta);
     SV_CHECK_THINKFIRST(sv);
-    if (SvLEN(sv))
-       assert(delta <= SvLEN(sv));
-    else
-       assert(delta <= SvCUR(sv));
+    max_delta = SvLEN(sv) ? SvLEN(sv) : SvCUR(sv);
+    if (delta > max_delta)
+       Perl_croak(aTHX_ "panic: sv_chop ptr=%p (was %p), start=%p, end=%p",
+                  SvPVX_const(sv) + delta, ptr, SvPVX_const(sv),
+                  SvPVX_const(sv) + max_delta);
 
     if (!SvOOK(sv)) {
        if (!SvLEN(sv)) { /* make copy of shared string */