Skip to content

Perl_repeatcpy() arg 4 "IV count" has overflow on 32b CPUs #23243

Open
@bulk88

Description

@bulk88

Description

#define PERL_REPEATCPY_LINEAR 4
void
Perl_repeatcpy(char *to, const char *from, SSize_t len, IV count)
{
    PERL_ARGS_ASSERT_REPEATCPY;

    assert(len >= 0);

    if (count < 0)
        croak_memory_wrap();

    if (len == 1)
        memset(to, *from, count);
    else if (count) {

Most related commits that I found:

26e1303 don't segfault given string repeat count larger than 2^31
2709980 avoid calling memset with a negative count
https://nvd.nist.gov/vuln/detail/CVE-2012-5195

Steps to Reproduce

Perl_repeatcpy() arg 4 bug is not reachable from PP from my limited test, through 1 of 2 libperl funcs that use Perl_repeatcpy(). I didn't try func 2. Fact check and verify this yourself, but all callers, 2 func, 3 call sites total, are doing their own bounds checking, which makes the bound checking attempts in Perl_repeatcpy() pointless or inappropriate API design or inappropriate delegation and abstraction of responsibilities.

5.41.7 Win64

C:\sources\perl5>perl -E" sub mks { return 'a' x 0xFFFFFFFFFFFFFFFF} print(mks()
);" > t3.txt
Out of memory in perl:util:safesysrealloc
panic: fold_constants JMPENV_PUSH returned 2 at -e line 1.
Free to wrong pool 4303b8 not 4275c0 at (null) line 1 during global destruction.

strawberry `uname='Win32 strawberry-perl 5.32.1.1 #1 Sun Jan 24 12:17:47 2021 i386'

C:\sources>perl -E" sub mks { return 'a' x 0x80000000} print(mks());" > t3.txt
Out of memory!
panic: fold_constants JMPENV_PUSH returned 2 at -e line 1.
Free to wrong pool 6cc780 not 6cc7b0 at (null) line 1 during global destruction.

got SEGV popup on windows ^^^

C:\sources>perl -E" sub mks { return 'abcdefgh' x 0x80000000} print(mks());" > t
3.txt
Out of memory during string extend at -e line 1.
C:\sources>perl -E" sub mks { return 'abcdefgh' x 0x8000000} print(mks());" > t3
.txt
Out of memory!
C:\sources>perl -E" sub mks { return @{$_[0]} x 0x100000000;} foreach(mks(['a'])
) {print $_};" > t3.txt
Out of memory during string extend at -e line 1.
C:\sources>perl -E" sub mks { return (@{$_[0]}) x 0x100000000;} foreach(mks(['a'
])) {print $_};" > t3.txt
Out of memory during list extend at -e line 1.

Expected behavior
Use Size_t type for arg 4 on all builds configs, the way it should've been written from day 1.

I don't have any opinion or proposal on how to correctly fix arg 4. Many questions:
but statement if (i64_count < 0) croak_memory_wrap(); is useless on a 32b CPU.
Which call frame/context does the 64b IV -> 32b size_t cast or truncate and bounds check logic? 64b IVs/int64_t on 32b CPUs is always emulated by the C compiler using multiple instructions 4 byte/32bit CPU ops.

Make a PvREPEATCPY() macro to do the bounds check and truncate in the caller?

Perl_repeatcpy is marked as public API, now what? What is the policy on breaking DarkPAN?

NOTE: 2 callers in libperl, 0 hits on grepcpan. Someone else should repeat my search attempts.

Deprecate, mathom, "no warning" delete the function by renaming to Perl_repeatcpy2 or Perl_repeatcpyn, etc?

Keep overflow hazard broken version as a libperl export under current name, Perl_repeatcpy and make a non exported Perl_repeatcpy_p for PERL_CORE?

I was happy to find Perl_repeatcpy exists in libperl's toolkit and had a thought of maybe using it myself in a future perl FOSS patch, vs DIYing it the traditional way with for(;;i++) {size_t[i] = size_t[i];}, but that plan changed after reading Perl_repeatcpy's src code.

Perl configuration

Summary of my perl5 (revision 5 version 41 subversion 12) configuration:
  Derived from: ec918d82932a068cc3f73beb4658a99acc1556e0
  Platform:
    osname=MSWin32
    osvers=6.1.7601
    archname=MSWin32-x64-multi-thread
    uname=''
    config_args='undef'
    hint=recommended
    useposix=true
    d_sigaction=undef
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=undef
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
  Compiler:
    cc='cl'
    ccflags ='-nologo -GF -W3 -MD -DWIN32 -D_CONSOLE -DNO_STRICT -DWIN64 -D_CRT_
SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_WINSOCK_DEPRECATED_NO_WARNING
S -DPERL_TEXTMODE_SCRIPTS -DMULTIPLICITY -DPERL_IMPLICIT_SYS -DUSE_PERLIO'
    optimize='-O1 -Zi -GL -fp:precise'
    cppflags='-DWIN32'
    ccversion='19.36.32535'
    gccversion=''
    gccosandvers=''
    intsize=4
    longsize=4
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=undef
    longlongsize=8
    d_longdbl=define
    longdblsize=8
    longdblkind=0
    ivtype='__int64'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='__int64'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='link'
    ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf -ltcg -libpath:"c:\perl\
lib\CORE" -machine:AMD64 -subsystem:console,"5.02"'
    libpth="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSV
C\14.36.32532\\lib\x64"
    libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.li
b advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.l
ib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib
 vcruntime.lib ucrt.lib
    perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg3
2.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_
32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt
.lib vcruntime.lib ucrt.lib
    libc=ucrt.lib
    so=dll
    useshrplib=true
    libperl=perl541.lib
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs
    dlext=dll
    d_dlsymun=undef
    ccdlflags=' '
    cccdlflags=' '
    lddlflags='-dll -nologo -nodefaultlib -debug -opt:ref,icf -ltcg -libpath:"c:
\perl\lib\CORE" -machine:AMD64 -subsystem:console,"5.02"'


Characteristics of this binary (from libperl):
  Compile-time options:
    HAS_LONG_DOUBLE
    HAS_TIMES
    HAVE_INTERP_INTERN
    MULTIPLICITY
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_HASH_FUNC_SIPHASH13
    PERL_HASH_USE_SBOX32
    PERL_IMPLICIT_SYS
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    PERL_USE_SAFE_PUTENV
    USE_64_BIT_INT
    USE_ITHREADS
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
    USE_THREAD_SAFE_LOCALE
  Locally applied patches:
    uncommitted-changes
  Built under MSWin32
  Compiled at May  2 2025 12:21:18
  %ENV:
    PERL_JSON_BACKEND="Cpanel::JSON::XS"
    PERL_YAML_BACKEND="YAML::XS"
  @INC:
    C:/sources/perl5/lib

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions