From: Vincent Pit Date: Thu, 28 May 2009 22:34:04 +0000 (+0200) Subject: Prevent bogus invalid syntaxes caused by reallocated memory chunks X-Git-Tag: v0.14~5 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2Findirect.git;a=commitdiff_plain;h=8291ef989ac98ee2cb53a6098eed7aa7c3ed0ca8 Prevent bogus invalid syntaxes caused by reallocated memory chunks Make sure that all our check functions reset a possible previous entry in the pointer table. Then, check in ck_entersub that the object op (the first kid after the pushmark) is of a proper type, so that we are pretty sure that its map entry has been either reset or filled. --- diff --git a/MANIFEST b/MANIFEST index aa5b24c..aee4fac 100644 --- a/MANIFEST +++ b/MANIFEST @@ -14,9 +14,12 @@ t/21-bad.t t/22-bad-mixed.t t/30-scope.t t/40-threads.t +t/41-memory.t t/91-pod.t t/92-pod-coverage.t t/95-portability-files.t t/99-kwalitee.t +t/lib/indirect/Test0/Fffff/Vvvvvvv.pm +t/lib/indirect/Test0/Oooooo/Pppppppp.pm t/lib/indirect/TestRequired1.pm t/lib/indirect/TestRequired2.pm diff --git a/indirect.xs b/indirect.xs index 4e538b3..eb6f01f 100644 --- a/indirect.xs +++ b/indirect.xs @@ -167,6 +167,7 @@ typedef struct { #include "ptable.h" #define ptable_store(T, K, V) ptable_store(aTHX_ (T), (K), (V)) +#define ptable_delete(T, K) ptable_delete(aTHX_ (T), (K)) #define ptable_clear(T) ptable_clear(aTHX_ (T)) #define ptable_free(T) ptable_free(aTHX_ (T)) @@ -391,6 +392,13 @@ STATIC const char *indirect_map_fetch(pTHX_ const OP *o, SV ** const name) { return INT2PTR(const char *, SvUVX(val)); } +STATIC void indirect_map_delete(pTHX_ const OP *o) { +#define indirect_map_delete(O) indirect_map_delete(aTHX_ (O)) + dMY_CXT; + + ptable_delete(MY_CXT.map, o); +} + /* --- Check functions ----------------------------------------------------- */ STATIC const char *indirect_find(pTHX_ SV *sv, const char *s) { @@ -426,10 +434,13 @@ STATIC OP *indirect_ck_const(pTHX_ OP *o) { if (indirect_hint()) { SV *sv = cSVOPo_sv; - if (SvPOK(sv) && (SvTYPE(sv) >= SVt_PV)) + if (SvPOK(sv) && (SvTYPE(sv) >= SVt_PV)) { indirect_map_store(o, indirect_find(sv, PL_oldbufptr), sv); + return o; + } } + indirect_map_delete(o); return o; } @@ -494,7 +505,10 @@ STATIC OP *indirect_ck_rv2sv(pTHX_ OP *o) { } done: - return CALL_FPTR(indirect_old_ck_rv2sv)(aTHX_ o); + o = CALL_FPTR(indirect_old_ck_rv2sv)(aTHX_ o); + + indirect_map_delete(o); + return o; } /* ... ck_padany ........................................................... */ @@ -515,9 +529,11 @@ STATIC OP *indirect_ck_padany(pTHX_ OP *o) { sv = sv_2mortal(newSVpvn("$", 1)); sv_catpvn_nomg(sv, s, t - s + 1); indirect_map_store(o, s, sv); + return o; } } + indirect_map_delete(o); return o; } @@ -544,7 +560,10 @@ STATIC OP *indirect_ck_method(pTHX_ OP *o) { } done: - return CALL_FPTR(indirect_old_ck_method)(aTHX_ o); + o = CALL_FPTR(indirect_old_ck_method)(aTHX_ o); + + indirect_map_delete(o); + return o; } /* ... ck_entersub ......................................................... */ @@ -572,6 +591,18 @@ STATIC OP *indirect_ck_entersub(pTHX_ OP *o) { oop = oop->op_sibling; mop = lop->op_last; + if (!oop) + goto done; + + switch (oop->op_type) { + case OP_CONST: + case OP_RV2SV: + case OP_PADSV: + break; + default: + goto done; + } + if (mop->op_type == OP_METHOD) mop = cUNOPx(mop)->op_first; else if (mop->op_type != OP_METHOD_NAMED) diff --git a/ptable.h b/ptable.h index 92d1a04..ba275ba 100644 --- a/ptable.h +++ b/ptable.h @@ -117,6 +117,16 @@ STATIC void *ptable_fetch(const ptable * const t, const void * const key) { } #endif /* !ptable_fetch */ +STATIC void PTABLE_PREFIX(_delete)(pPTBL_ const ptable * const t, const void * const key) { + ptable_ent *const ent = ptable_find(t, key); + + if (ent) { + void *val = ent->val; + PTABLE_VAL_FREE(val); + ent->val = NULL; + } +} + #ifndef ptable_split STATIC void ptable_split(pPTBLMS_ ptable * const t) { #define ptable_split(T) ptable_split(aPTBLMS_ (T)) diff --git a/t/41-memory.t b/t/41-memory.t new file mode 100644 index 0000000..0228929 --- /dev/null +++ b/t/41-memory.t @@ -0,0 +1,8 @@ +#!perl -T + +use lib 't/lib'; + +use Test::More tests => 1; + +eval "require indirect::Test0::Oooooo::Pppppppp"; +is($@, '', 'memory reallocation to an uncatched optype'); diff --git a/t/lib/indirect/Test0/Fffff/Vvvvvvv.pm b/t/lib/indirect/Test0/Fffff/Vvvvvvv.pm new file mode 100644 index 0000000..8da99ea --- /dev/null +++ b/t/lib/indirect/Test0/Fffff/Vvvvvvv.pm @@ -0,0 +1,12 @@ +package indirect::Test0::Fffff::Vvvvvvv; + +use warnings; +use strict; + +my $f; +sub import { + my($class, %args) = @_; + $f = bless({ x => $args{x}, y => $args{y} }, $class); +} + +1; diff --git a/t/lib/indirect/Test0/Oooooo/Pppppppp.pm b/t/lib/indirect/Test0/Oooooo/Pppppppp.pm new file mode 100644 index 0000000..f666da5 --- /dev/null +++ b/t/lib/indirect/Test0/Oooooo/Pppppppp.pm @@ -0,0 +1,15 @@ +package indirect::Test0::Oooooo::Pppppppp; + +use strict; +no indirect ":fatal"; + +use indirect::Test0::Fffff::Vvvvvvv + z => 0, + x => sub { }, + y => sub { }; + +use indirect::Test0::Fffff::Vvvvvvv + t => [xxxx=>qw(xxxxxx xxxxxxx)], + x => sub { $_[0]->method }; + +1;