• Bug#1092774: libfcgi: CVE-2025-23016 (5/5)

    From Bastian Germann@21:1/5 to All on Mon Apr 14 20:50:01 2025
    [continued from previous message]

    + return EOF;
    + been_here = 1;
    + }
    + else {
    + FCGX_Request *fcgx_req = request->requestPtr;
    + int acceptResult;
    +
    + FCGI_Finish(request);
    +#if defined(USE_ITHREADS)
    + MUTEX_LOCK(&accept_mutex);
    +#endif
    + acceptResult = FCGX_Accept_r(fcgx_req);
    +#if defined(USE_ITHREADS)
    + MUTEX_UNLOCK(&accept_mutex);
    +#endif
    + if(acceptResult < 0) {
    + return acceptResult;
    + }
    +
    + populate_env(fcgx_req->envp, request->hvEnv);
    +
    + if (!request->svout) {
    + newSVrv(request->svout = newSV(0), "FCGI::Stream");
    + newSVrv(request->sverr = newSV(0), "FCGI::Stream");
    + newSVrv(request->svin = newSV(0), "FCGI::Stream");
    + }
    + sv_setiv(SvRV(request->svout), INT2PTR(IV, fcgx_req->out));
    + sv_setiv(SvRV(request->sverr), INT2PTR(IV, fcgx_req->err));
    + sv_setiv(SvRV(request->svin), INT2PTR(IV, fcgx_req->in));
    + FCGI_Bind(request);
    + request->accepted = TRUE;
    + }
    + return 0;
    +}
    +
    +static void
    +FCGI_Finish(FCGP_Request* request) {
    + int was_bound;
    + dTHX;
    +
    + if(!request->accepted)
    + return;
    +
    + if (was_bound = request->bound)
    + FCGI_UndoBinding(request);
    + if (was_bound)
    + FCGX_Finish_r(request->requestPtr);
    + else
    + FCGX_Free(request->requestPtr, 1);
    + request->accepted = FALSE;
    +}
    +
    +static int
    +FCGI_StartFilterData(FCGP_Request* request) {
    + return request->requestPtr->in ?
    + FCGX_StartFilterData(request->requestPtr->in) : -1;
    +}
    +
    +static FCGP_Request *
    +FCGI_Request(GV *in, GV *out, GV *err, HV *env, int socket, int flags) {
    + FCGX_Request* fcgx_req;
    + FCGP_Request* req;
    +
    + Newz(551, fcgx_req, 1, FCGX_Request);
    + FCGX_InitRequest(fcgx_req, socket, flags);
    + Newz(551, req, 1, FCGP_Request);
    + req->requestPtr = fcgx_req;
    + SvREFCNT_inc(in);
    + req->gv[0] = in;
    + SvREFCNT_inc(out);
    + req->gv[1] = out;
    + SvREFCNT_inc(err);
    + req->gv[2] = err;
    + SvREFCNT_inc(env);
    + req->hvEnv = env;
    +
    + return req;
    +}
    +
    +static void
    +FCGI_Release_Request(FCGP_Request *req) {
    + SvREFCNT_dec(req->gv[0]);
    + SvREFCNT_dec(req->gv[1]);
    + SvREFCNT_dec(req->gv[2]);
    + SvREFCNT_dec(req->hvEnv);
    + FCGI_Finish(req);
    + Safefree(req->requestPtr);
    + Safefree(req);
    +}
    +
    +static void
    +FCGI_Init() {
    +#if defined(USE_ITHREADS)
    + dTHX;
    + MUTEX_INIT(&accept_mutex);
    +#endif
    + FCGX_Init();
    +}
    +
    +typedef FCGX_Stream* FCGI__Stream;
    +typedef FCGP_Request* FCGI;
    +typedef GV* GLOBREF;
    +typedef HV* HASHREF;
    +
    +MODULE = FCGI PACKAGE = FCGI PREFIX = FCGI_
    +
    +BOOT:
    + FCGI_Init();
    +
    +SV *
    +RequestX(in, out, err, env, socket, flags)
    + GLOBREF in;
    + GLOBREF out;
    + GLOBREF err;
    + HASHREF env;
    + int socket;
    + int flags;
    + PROTOTYPE: ***$$$
    + CODE:
    + RETVAL = sv_setref_pv(newSV(0), "FCGI",
    + FCGI_Request(in, out, err, env, socket, flags));
    + OUTPUT:
    + RETVAL
    +
    +int
    +OpenSocket(path, backlog)
    + char* path;
    + int backlog;
    + PROTOTYPE: $$
    + CODE:
    + RETVAL = FCGX_OpenSocket(path, backlog);
    + OUTPUT:
    + RETVAL
    +
    +void
    +CloseSocket(socket)
    + int socket;
    + PROTOTYPE: $
    + CODE:
    + close(socket);
    +
    +int
    +FCGI_Accept(request)
    + FCGI request;
    + PROTOTYPE: $
    +
    +void
    +FCGI_Finish(request)
    + FCGI request;
    + PROTOTYPE: $
    +
    +void
    +FCGI_Flush(request)
    + FCGI request;
    + PROTOTYPE: $
    +
    +HV *
    +GetEnvironment(request)
    + FCGI request;
    + PROTOTYPE: $
    + CODE:
    + RETVAL = request->hvEnv;
    + OUTPUT:
    + RETVAL
    +
    +void
    +GetHandles(request)
    + FCGI request;
    + PROTOTYPE: $
    + PREINIT:
    + int i;
    + PPCODE:
    + EXTEND(sp,3);
    + for (i = 0; i < 3; ++i)
    + PUSHs(sv_2mortal(newRV((SV *) request->gv[i])));
    +
    +int
    +FCGI_IsFastCGI(request)
    + FCGI request;
    + PROTOTYPE: $
    +
    +void
    +Detach(request)
    + FCGI request;
    + PROTOTYPE: $
    + CODE:
    + if (request->accepted && request->bound) {
    + FCGI_UndoBinding(request);
    + FCGX_Detach(request->requestPtr);
    + }
    +
    +void
    +Attach(request)
    + FCGI request;
    + PROTOTYPE: $
    + CODE:
    + if (request->accepted && !request->bound) {
    + FCGI_Bind(request);
    + FCGX_Attach(request->requestPtr);
    + }
    +
    +void
    +LastCall(request)
    + FCGI request;
    + PROTOTYPE: $
    + CODE:
    + FCGX_ShutdownPending();
    +
    +int
    +FCGI_StartFilterData(request)
    + FCGI request;
    + PROTOTYPE: $
    +
    +void
    +DESTROY(request)
    + FCGI request;
    + CODE:
    + FCGI_Release_Request(request);
    +
    +MODULE = FCGI PACKAGE = FCGI::Stream
    +
    +SV *
    +PRINT(stream, ...)
    + FCGI::Stream stream;
    + PREINIT:
    + int n;
    + STRLEN len;
    + register char *str;
    + bool ok = TRUE;
    + CODE:
    + for (n = 1; ok && n < items; ++n) {
    +#ifdef DO_UTF8
    + if (DO_UTF8(ST(n)) && !sv_utf8_downgrade(ST(n), 1) && ckWARN_d(WARN_UTF8))
    + Perl_warner(aTHX_ WARN_UTF8, WIDE_CHAR_DEPRECATION_MSG,
    + "FCGI::Stream::PRINT");
    +#endif
    + str = (char *)SvPV(ST(n),len);
    + if (FCGX_PutStr(str, len, stream) < 0)
    + ok = FALSE;
    + }
    + if (ok && SvTRUEx(perl_get_sv("|", FALSE)) && FCGX_FFlush(stream) < 0)
    + ok = FALSE;
    + RETVAL = ok ? &PL_sv_yes : &PL_sv_undef;
    + OUTPUT:
    + RETVAL
    +
    +int
    +WRITE(stream, bufsv, len, ...)
    + FCGI::Stream stream;
    + SV *bufsv;
    + int len;
    + PREINIT:
    + int offset;
    + char *buf;
    + STRLEN blen;
    + int n;
    + CODE:
    + offset = (items == 4) ? (int)SvIV(ST(3)) : 0;
    +#ifdef DO_UTF8
    + if (DO_UTF8(bufsv) && !sv_utf8_downgrade(bufsv, 1) && ckWARN_d(WARN_UTF8)) + Perl_warner(aTHX_ WARN_UTF8, WIDE_CHAR_DEPRECATION_MSG,
    + "FCGI::Stream::WRITE");
    +#endif
    + buf = SvPV(bufsv, blen);
    + if (offset < 0) offset += blen;
    + if (len > blen - offset)
    + len = blen - offset;
    + if (offset < 0 || offset >= blen ||
    + (n = FCGX_PutStr(buf+offset, len, stream)) < 0)
    + ST(0) = &PL_sv_undef;
    + else {
    + ST(0) = sv_newmortal();
    + sv_setiv(ST(0), n);
    + }
    +
    +void
    +READ(stream, bufsv, len, ...)
    + FCGI::Stream stream;
    + SV *bufsv;
    + int len;
    + PREINIT:
    + int offset = 0;
    + char *buf;
    + STRLEN blen;
    + CODE:
    + if (items < 3 || items > 4)
    + croak("Usage: FCGI::Stream::READ(STREAM, SCALAR, LENGTH [, OFFSET ])");
    + if (len < 0)
    + croak("Negative length");
    + if (!SvOK(bufsv))
    + sv_setpvn(bufsv, "", 0);
    +#ifdef DO_UTF8
    + if (DO_UTF8(bufsv) && !sv_utf8_downgrade(bufsv, 1) && ckWARN_d(WARN_UTF8)) + Perl_warner(aTHX_ WARN_UTF8, WIDE_CHAR_DEPRECATION_MSG,
    + "FCGI::Stream::READ");
    +#endif
    + buf = SvPV_force(bufsv, blen);
    + if (items == 4) {
    + offset = SvIV(ST(3));
    + if (offset < 0) {
    + if (-offset > (int)blen)
    + croak("Offset outside string");
    + offset += blen;
    + }
    + }
    + buf = SvGROW(bufsv, len + offset + 1);
    + if (offset > blen)
    + Zero(buf + blen, offset - blen, char);
    + len = FCGX_GetStr(buf + offset, len, stream);
    + SvCUR_set(bufsv, len + offset);
    + *SvEND(bufsv) = '\0';
    + (void)SvPOK_only(bufsv);
    + SvSETMAGIC(bufsv);
    + XSRETURN_IV(len);
    +
    +SV *
    +GETC(stream)
    + FCGI::Stream stream;
    + PREINIT:
    + int retval;
    + CODE:
    + if ((retval = FCGX_GetChar(stream)) != -1) {
    + ST(0) = sv_newmortal();
    + sv_setpvf(ST(0), "%c", retval);
    + }
    + else
    + ST(0) = &PL_sv_undef;
    +
    +SV *
    +EOF(stream, called=0)
    + FCGI::Stream stream;
    + IV called;
    + CODE:
    + RETVAL = boolSV(FCGX_HasSeenEOF(stream));
    + OUTPUT:
    + RETVAL
    +
    +void
    +FILENO(stream)
    + FCGI::Stream stream;
    + CODE:
    + if (FCGX_HasSeenEOF(stream) != 0)
    + XSRETURN_UNDEF;
    + else
    + XSRETURN_IV(-1);
    +
    +bool
    +CLOSE(stream)
    + FCGI::Stream stream;
    + CODE:
    + RETVAL = FCGX_FClose(stream) != -1;
    + OUTPUT:
    + RETVAL
    diff -Nru libfcgi-2.4.2/perl/.gitignore libfcgi-2.4.5/perl/.gitignore
    --- libfcgi-2.4.2/perl/.gitignore 2019-02-19 12:19:19.000000000 +0100
    +++ libfcgi-2.4.5/perl/.gitignore 2025-04-14 19:35:59.000000000 +0200
    @@ -8,3 +8,7 @@
    pm_to_blib
    fcgi_config.*
    fcgi_config_x86.h
    +Makefile
    +config.log
    +config.status
    +MYMETA.*
    diff -Nru libfcgi-2.4.2/perl/Makefile.PL libfcgi-2.4.5/perl/Makefile.PL
    --- libfcgi-2.4.2/perl/Makefile.PL 2019-02-19 12:19:19.000000000 +0100
    +++ libfcgi-2.4.5/perl/Makefile.PL 2025-04-14 19:35:59.000000000 +0200
    @@ -1,64 +1,60 @@
    # $Id: Makefile.PL,v 1.33 2002/12/15 19:40:19 skimo Exp $

    +use 5.006;
    use ExtUtils::MakeMaker;
    use IO::File;
    use Config;
    use Cwd 'cwd';
    use Getopt::Long;
    +use File::Copy qw(copy);

    @h1 = qw(fastcgi.h fcgiapp.h fcgimisc.h fcgios.h);
    @h = (@h1, 'fcgi_config.h');
    @o = qw(FCGI.o);
    -@dist1 = qw(LICENSE.TERMS);
    +@dist1 = qw(LICENSE);
    @dist2 = qw(fcgiapp.c os_unix.c os_win32.c);
    @dist3 = (@h1, qw(fcgi_config_x86.h));

    -GetOptions ("pure-perl!" => \$pure,
    - "use-installed:s" => \$useinstalled);
    -