--- perl-5.8.7/t/lib/warnings/sv.CVE-2005-3962-bz174684 2004-03-18 07:51:14.000000000 -0500 +++ perl-5.8.7/t/lib/warnings/sv 2005-12-14 12:40:55.000000000 -0500 @@ -301,12 +301,12 @@ printf F "%\x02" ; $a = sprintf "%\x02" ; EXPECT -Invalid conversion in sprintf: "%z" at - line 5. -Invalid conversion in sprintf: end of string at - line 7. -Invalid conversion in sprintf: "%\002" at - line 9. Invalid conversion in printf: "%z" at - line 4. +Invalid conversion in sprintf: "%z" at - line 5. Invalid conversion in printf: end of string at - line 6. +Invalid conversion in sprintf: end of string at - line 7. Invalid conversion in printf: "%\002" at - line 8. +Invalid conversion in sprintf: "%\002" at - line 9. ######## # sv.c use warnings 'misc' ; --- perl-5.8.7/t/op/sprintf.t.CVE-2005-3962-bz174684 2003-09-01 03:41:07.000000000 -0400 +++ perl-5.8.7/t/op/sprintf.t 2005-12-14 12:53:09.000000000 -0500 @@ -385,3 +385,8 @@ >%4$K %d< >[45, 67]< >%4$K 45 INVALID< >%d %K %d< >[23, 45]< >23 %K 45 INVALID< >%*v*999\$d %d %d< >[11, 22, 33]< >%*v*999\$d 11 22 INVALID< +>%#b< >0< >0< +>%#o< >0< >0< +>%#x< >0< >0< +>%2918905856$v2d< >''< >< +>%*2918905856$v2d< >''< > UNINIT< --- perl-5.8.7/t/op/sprintf2.t.CVE-2005-3962-bz174684 2004-02-09 16:37:13.000000000 -0500 +++ perl-5.8.7/t/op/sprintf2.t 2005-12-14 12:50:39.000000000 -0500 @@ -6,7 +6,7 @@ require './test.pl'; } -plan tests => 3; +plan tests => 7 + 256; is( sprintf("%.40g ",0.01), @@ -26,3 +26,43 @@ q(width calculation under utf8 upgrade) ); } + +# Used to mangle PL_sv_undef +fresh_perl_is( + 'print sprintf "xxx%n\n"; print undef', + 'Modification of a read-only value attempted at - line 1.', + { switches => [ '-w' ] }, + q(%n should not be able to modify read-only constants), +); + +# check %NNN$ for range bounds, especially negative 2's complement +{ + my ($warn, $bad) = (0,0); + local $SIG{__WARN__} = sub { + if ($_[0] =~ /uninitialized/) { + $warn++ + } + else { + $bad++ + } + }; + my $result = sprintf join('', map("%$_\$s%" . ~$_ . '$s', 1..20)), + qw(a b c d); + is($result, "abcd", "only four valid values"); + is($warn, 36, "expected warnings"); + is($bad, 0, "unexpected warnings"); +} +{ + foreach my $ord (0 .. 255) { + my $bad = 0; + local $SIG{__WARN__} = sub { + unless ($_[0] =~ /^Invalid conversion in sprintf/ || + $_[0] =~ /^Use of uninitialized value in sprintf/) { + warn $_[0]; + $bad++; + } + }; + my $r = eval {sprintf '%v' . chr $ord}; + is ($bad, 0, "pattern '%v' . chr $ord"); + } +} --- perl-5.8.7/opcode.h.CVE-2005-3962-bz174684 2005-05-27 12:29:50.000000000 -0400 +++ perl-5.8.7/opcode.h 2005-12-14 12:40:55.000000000 -0500 @@ -1585,7 +1585,7 @@ 0x0022281c, /* vec */ 0x0122291c, /* index */ 0x0122291c, /* rindex */ - 0x0004280f, /* sprintf */ + 0x0004280d, /* sprintf - WAS 0x0004280f before patch #26283 */ 0x00042805, /* formline */ 0x0001379e, /* ord */ 0x0001378e, /* chr */ --- perl-5.8.7/op.c.CVE-2005-3962-bz174684 2005-04-22 10:12:32.000000000 -0400 +++ perl-5.8.7/op.c 2005-12-14 12:40:55.000000000 -0500 @@ -2076,7 +2076,9 @@ /* XXX might want a ck_negate() for this */ cUNOPo->op_first->op_private &= ~OPpCONST_STRICT; break; - case OP_SPRINTF: +/* Removed as part of fix for CVE-2005-3962 / Upstream patch 26283 : + * case OP_SPRINTF: + */ case OP_UCFIRST: case OP_LCFIRST: case OP_UC: --- perl-5.8.7/makedef.pl.CVE-2005-3962-bz174684 2005-05-09 09:27:41.000000000 -0400 +++ perl-5.8.7/makedef.pl 2005-12-14 12:40:55.000000000 -0500 @@ -635,11 +635,13 @@ )]; } -if ($define{'PERL_MALLOC_WRAP'}) { - emit_symbols [qw( - PL_memory_wrap - )]; -} +# Removed as part of fix for CVE-2005-3962 / CVE-2005-3962 / +# Upstream patch #26283 +# if ($define{'PERL_MALLOC_WRAP'}) { +# emit_symbols [qw( +# PL_memory_wrap +# )]; +#} unless ($define{'USE_5005THREADS'} || $define{'USE_ITHREADS'}) { skip_symbols [qw( --- perl-5.8.7/ext/Sys/Syslog/Syslog.pm.CVE-2005-3962-bz174684 2005-04-22 07:53:56.000000000 -0400 +++ perl-5.8.7/ext/Sys/Syslog/Syslog.pm 2005-12-14 12:40:55.000000000 -0500 @@ -1,14 +1,13 @@ package Sys::Syslog; require 5.006; require Exporter; -require DynaLoader; use Carp; use strict; -our @ISA = qw(Exporter DynaLoader); +our @ISA = qw(Exporter); our @EXPORT = qw(openlog closelog setlogmask syslog); our @EXPORT_OK = qw(setlogsock); -our $VERSION = '0.06'; +our $VERSION = '0.08'; # it would be nice to try stream/unix first, since that will be # most efficient. However streams are dodgy - see _syslog_send_stream @@ -54,26 +53,38 @@ =item openlog $ident, $logopt, $facility +Opens the syslog. I<$ident> is prepended to every message. I<$logopt> contains zero or more of the words I, I, I. The cons option is ignored, since the failover mechanism will drop down to the console automatically if all other media fail. I<$facility> specifies the part of the system to report about, for example LOG_USER or LOG_LOCAL0: see your C documentation for the facilities available in -your system. +your system. This function will croak if it can't connect to the syslog +daemon. B +=item syslog $priority, $message + =item syslog $priority, $format, @args -If I<$priority> permits, logs I<($format, @args)> -printed as by C, with the addition that I<%m> -is replaced with C<"$!"> (the latest error message). +If I<$priority> permits, logs I<$message> or I +with the addition that I<%m> in $message or $format is replaced with +C<"$!"> (the latest error message). If you didn't use openlog() before using syslog(), syslog will try to guess the I<$ident> by extracting the shortest prefix of I<$format> that ends in a ":". +Note that Sys::Syslog version v0.07 and older passed the $message as +the formatting string to sprintf() even when no formatting arguments +were provided. If the code calling syslog() might execute with older +versions of this module, make sure to call the function as +syslog($priority, "%s", $message) instead of syslog($priority, +$message). This protects against hostile formatting sequences that +might show up if $message contains tainted data. + =item setlogmask $mask_priority Sets log mask I<$mask_priority> and returns the old mask. @@ -175,7 +186,8 @@ goto &$AUTOLOAD; } -bootstrap Sys::Syslog $VERSION; +require XSLoader; +XSLoader::load('Sys::Syslog', $VERSION); our $maskpri = &LOG_UPTO(&LOG_DEBUG); @@ -316,9 +328,16 @@ $whoami .= "[$$]" if our $lo_pid; - $mask =~ s/(?$whoami: $message\0"; --- perl-5.8.7/opcode.pl.CVE-2005-3962-bz174684 2004-12-01 08:54:30.000000000 -0500 +++ perl-5.8.7/opcode.pl 2005-12-14 12:40:55.000000000 -0500 @@ -606,7 +606,7 @@ index index ck_index isT@ S S S? rindex rindex ck_index isT@ S S S? -sprintf sprintf ck_fun mfst@ S L +sprintf sprintf ck_fun mst@ S L formline formline ck_fun ms@ S L ord ord ck_fun ifsTu% S? chr chr ck_fun fsTu% S? --- perl-5.8.7/handy.h.CVE-2005-3962-bz174684 2005-04-20 12:33:28.000000000 -0400 +++ perl-5.8.7/handy.h 2005-12-14 12:40:55.000000000 -0500 @@ -598,91 +598,65 @@ =cut */ -#ifndef lint - #define NEWSV(x,len) newSV(len) #ifdef PERL_MALLOC_WRAP #define MEM_WRAP_CHECK(n,t) \ - (void)((n)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(PL_memory_wrap),0):0) + (void)((sizeof(t)>1?(n):1)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(PL_memory_wrap),0):0) #define MEM_WRAP_CHECK_1(n,t,a) \ - (void)((n)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(a),0):0) + (void)((sizeof(t)>1?(n):1)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(a),0):0) #define MEM_WRAP_CHECK_2(n,t,a,b) \ - (void)((n)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(a,b),0):0) + (void)((sizeof(t)>1?(n):1)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(a,b),0):0) +#define MEM_WRAP_CHECK_(n,t) MEM_WRAP_CHECK(n,t), -#define New(x,v,n,t) (v = (MEM_WRAP_CHECK(n,t), (t*)safemalloc((MEM_SIZE)((n)*sizeof(t))))) -#define Newc(x,v,n,t,c) (v = (MEM_WRAP_CHECK(n,t), (c*)safemalloc((MEM_SIZE)((n)*sizeof(t))))) -#define Newz(x,v,n,t) (v = (MEM_WRAP_CHECK(n,t), (t*)safemalloc((MEM_SIZE)((n)*sizeof(t))))), \ - memzero((char*)(v), (n)*sizeof(t)) -#define Renew(v,n,t) \ - (v = (MEM_WRAP_CHECK(n,t), (t*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))) -#define Renewc(v,n,t,c) \ - (v = (MEM_WRAP_CHECK(n,t), (c*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))) -#define Safefree(d) safefree((Malloc_t)(d)) - -#define Move(s,d,n,t) (MEM_WRAP_CHECK(n,t), (void)memmove((char*)(d),(char*)(s), (n) * sizeof(t))) -#define Copy(s,d,n,t) (MEM_WRAP_CHECK(n,t), (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t))) -#define Zero(d,n,t) (MEM_WRAP_CHECK(n,t), (void)memzero((char*)(d), (n) * sizeof(t))) - -#define MoveD(s,d,n,t) (MEM_WRAP_CHECK(n,t), memmove((char*)(d),(char*)(s), (n) * sizeof(t))) -#define CopyD(s,d,n,t) (MEM_WRAP_CHECK(n,t), memcpy((char*)(d),(char*)(s), (n) * sizeof(t))) -#ifdef HAS_MEMSET -#define ZeroD(d,n,t) (MEM_WRAP_CHECK(n,t), memzero((char*)(d), (n) * sizeof(t))) -#else -/* Using bzero(), which returns void. */ -#define ZeroD(d,n,t) (MEM_WRAP_CHECK(n,t), memzero((char*)(d), (n) * sizeof(t)),d) -#endif - -#define Poison(d,n,t) (MEM_WRAP_CHECK(n,t), (void)memset((char*)(d), 0xAB, (n) * sizeof(t))) +#define PERL_STRLEN_ROUNDUP(n) ((void)(((n) > (MEM_SIZE)~0 - 2 * PERL_STRLEN_ROUNDUP_QUANTUM) ? (Perl_croak_nocontext(PL_memory_wrap),0):0),((n-1+PERL_STRLEN_ROUNDUP_QUANTUM)&~((MEM_SIZE)PERL_STRLEN_ROUNDUP_QUANTUM-1))) #else #define MEM_WRAP_CHECK(n,t) #define MEM_WRAP_CHECK_1(n,t,a) #define MEM_WRAP_CHECK_2(n,t,a,b) +#define MEM_WRAP_CHECK_(n,t) + +#define PERL_STRLEN_ROUNDUP(n) (((n-1+PERL_STRLEN_ROUNDUP_QUANTUM)&~((MEM_SIZE)PERL_STRLEN_ROUNDUP_QUANTUM-1))) -#define New(x,v,n,t) (v = (t*)safemalloc((MEM_SIZE)((n)*sizeof(t)))) -#define Newc(x,v,n,t,c) (v = (c*)safemalloc((MEM_SIZE)((n)*sizeof(t)))) -#define Newz(x,v,n,t) (v = (t*)safemalloc((MEM_SIZE)((n)*sizeof(t)))), \ +#endif + +#define Newx(v,n,t) (v = (MEM_WRAP_CHECK_(n,t) (t*)safemalloc((MEM_SIZE)((n)*sizeof(t))))) +#define Newxc(v,n,t,c) (v = (MEM_WRAP_CHECK_(n,t) (c*)safemalloc((MEM_SIZE)((n)*sizeof(t))))) +#define Newxz(v,n,t) (v = (MEM_WRAP_CHECK_(n,t) (t*)safemalloc((MEM_SIZE)((n)*sizeof(t))))), \ memzero((char*)(v), (n)*sizeof(t)) +/* pre 5.9.x compatibility */ +#define New(x,v,n,t) Newx(v,n,t) +#define Newc(x,v,n,t,c) Newxc(v,n,t,c) +#define Newz(x,v,n,t) Newxz(v,n,t) + #define Renew(v,n,t) \ - (v = (t*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t)))) + (v = (MEM_WRAP_CHECK_(n,t) (t*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))) #define Renewc(v,n,t,c) \ - (v = (c*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t)))) -#define Safefree(d) safefree((Malloc_t)(d)) - -#define Move(s,d,n,t) (void)memmove((char*)(d),(char*)(s), (n) * sizeof(t)) -#define Copy(s,d,n,t) (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t)) -#define Zero(d,n,t) (void)memzero((char*)(d), (n) * sizeof(t)) + (v = (MEM_WRAP_CHECK_(n,t) (c*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))) -#define MoveD(s,d,n,t) memmove((char*)(d),(char*)(s), (n) * sizeof(t)) -#define CopyD(s,d,n,t) memcpy((char*)(d),(char*)(s), (n) * sizeof(t)) -#ifdef HAS_MEMSET -#define ZeroD(d,n,t) memzero((char*)(d), (n) * sizeof(t)) +#ifdef PERL_POISON +#define Safefree(d) \ + (d ? (void)(safefree((Malloc_t)(d)), Poison(&(d), 1, Malloc_t)) : (void) 0) #else -#define ZeroD(d,n,t) ((void)memzero((char*)(d), (n) * sizeof(t)),d) +#define Safefree(d) safefree((Malloc_t)(d)) #endif -#define Poison(d,n,t) (void)memset((char*)(d), 0xAB, (n) * sizeof(t)) +#define Move(s,d,n,t) (MEM_WRAP_CHECK_(n,t) (void)memmove((char*)(d),(const char*)(s), (n) * sizeof(t))) +#define Copy(s,d,n,t) (MEM_WRAP_CHECK_(n,t) (void)memcpy((char*)(d),(const char*)(s), (n) * sizeof(t))) +#define Zero(d,n,t) (MEM_WRAP_CHECK_(n,t) (void)memzero((char*)(d), (n) * sizeof(t))) +#define MoveD(s,d,n,t) (MEM_WRAP_CHECK_(n,t) memmove((char*)(d),(const char*)(s), (n) * sizeof(t))) +#define CopyD(s,d,n,t) (MEM_WRAP_CHECK_(n,t) memcpy((char*)(d),(const char*)(s), (n) * sizeof(t))) +#ifdef HAS_MEMSET +#define ZeroD(d,n,t) (MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t))) +#else +/* Using bzero(), which returns void. */ +#define ZeroD(d,n,t) (MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)),d) #endif -#else /* lint */ - -#define New(x,v,n,s) (v = Null(s *)) -#define Newc(x,v,n,s,c) (v = Null(s *)) -#define Newz(x,v,n,s) (v = Null(s *)) -#define Renew(v,n,s) (v = Null(s *)) -#define Move(s,d,n,t) -#define Copy(s,d,n,t) -#define Zero(d,n,t) -#define MoveD(s,d,n,t) d -#define CopyD(s,d,n,t) d -#define ZeroD(d,n,t) d -#define Poison(d,n,t) -#define Safefree(d) (d) = (d) - -#endif /* lint */ +#define Poison(d,n,t) (MEM_WRAP_CHECK_(n,t) (void)memset((char*)(d), 0xAB, (n) * sizeof(t))) #ifdef USE_STRUCT_COPY #define StructCopy(s,d,t) (*((t*)(d)) = *((t*)(s))) --- perl-5.8.7/perl.h.CVE-2005-3962-bz174684 2005-12-14 12:40:55.000000000 -0500 +++ perl-5.8.7/perl.h 2005-12-14 12:40:55.000000000 -0500 @@ -720,6 +720,13 @@ #define MEM_SIZE Size_t +/* Round all values passed to malloc up, by default to a multiple of + sizeof(size_t) +*/ +#ifndef PERL_STRLEN_ROUNDUP_QUANTUM +#define PERL_STRLEN_ROUNDUP_QUANTUM Size_t_size +#endif + #if defined(STANDARD_C) && defined(I_STDDEF) # include # define STRUCT_OFFSET(s,m) offsetof(s,m) @@ -3332,10 +3339,8 @@ INIT("\"my\" variable %s can't be in a package"); EXTCONST char PL_no_localize_ref[] INIT("Can't localize through a reference"); -#ifdef PERL_MALLOC_WRAP EXTCONST char PL_memory_wrap[] INIT("panic: memory wrap"); -#endif EXTCONST char PL_uuemap[65] INIT("`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"); --- perl-5.8.7/sv.c.CVE-2005-3962-bz174684 2005-05-27 06:38:11.000000000 -0400 +++ perl-5.8.7/sv.c 2005-12-14 12:48:45.000000000 -0500 @@ -8589,9 +8589,12 @@ if (vectorarg) { if (args) vecsv = va_arg(*args, SV*); - else - vecsv = (evix ? evix <= svmax : svix < svmax) ? - svargs[evix ? evix-1 : svix++] : &PL_sv_undef; + else if (evix) { + vecsv = (evix > 0 && evix <= svmax) + ? svargs[evix-1] : &PL_sv_undef; + } else { + vecsv = svix < svmax ? svargs[svix++] : &PL_sv_undef; + } dotstr = SvPVx(vecsv, dotstrlen); if (DO_UTF8(vecsv)) is_utf8 = TRUE; @@ -8601,12 +8604,13 @@ vecstr = (U8*)SvPVx(vecsv,veclen); vec_utf8 = DO_UTF8(vecsv); } - else if (efix ? efix <= svmax : svix < svmax) { + else if (efix ? (efix > 0 && efix <= svmax) : svix < svmax) { vecsv = svargs[efix ? efix-1 : svix++]; vecstr = (U8*)SvPVx(vecsv,veclen); vec_utf8 = DO_UTF8(vecsv); } else { + vecsv = &PL_sv_undef; vecstr = (U8*)""; veclen = 0; } @@ -8707,9 +8711,15 @@ if (vectorize) argsv = vecsv; - else if (!args) - argsv = (efix ? efix <= svmax : svix < svmax) ? - svargs[efix ? efix-1 : svix++] : &PL_sv_undef; + else if (!args) { + if (efix) { + const I32 i = efix-1; + argsv = (i >= 0 && i < svmax) ? svargs[i] : &PL_sv_undef; + } else { + argsv = (svix >= 0 && svix < svmax) + ? svargs[svix++] : &PL_sv_undef; + } + } switch (c = *q++) { @@ -8972,6 +8982,8 @@ *--eptr = '0'; break; case 2: + if (!uv) + alt = FALSE; do { dig = uv & 1; *--eptr = '0' + dig; @@ -9274,6 +9286,8 @@ /* calculate width before utf8_upgrade changes it */ have = esignlen + zeros + elen; + if (have < zeros) + Perl_croak_nocontext(PL_memory_wrap); if (is_utf8 != has_utf8) { if (is_utf8) { @@ -9301,6 +9315,9 @@ need = (have > width ? have : width); gap = need - have; + if (need >= (((STRLEN)~0) - SvCUR(sv) - dotstrlen - 1)) + Perl_croak_nocontext(PL_memory_wrap); + SvGROW(sv, SvCUR(sv) + need + dotstrlen + 1); p = SvEND(sv); if (esignlen && fill == '0') { --- perl-5.8.7/globvar.sym.CVE-2005-3962-bz174684 2000-08-14 11:22:14.000000000 -0400 +++ perl-5.8.7/globvar.sym 2005-12-14 12:51:12.000000000 -0500 @@ -66,3 +66,4 @@ vtbl_collxfrm vtbl_amagic vtbl_amagicelem +memory_wrap