Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:87743 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 66137 invoked from network); 13 Aug 2015 15:00:06 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 13 Aug 2015 15:00:06 -0000 Authentication-Results: pb1.pair.com header.from=danack@basereality.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=danack@basereality.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain basereality.com from 209.85.160.178 cause and error) X-PHP-List-Original-Sender: danack@basereality.com X-Host-Fingerprint: 209.85.160.178 mail-yk0-f178.google.com Received: from [209.85.160.178] ([209.85.160.178:34509] helo=mail-yk0-f178.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 98/E5-00702-4F0BCC55 for ; Thu, 13 Aug 2015 11:00:05 -0400 Received: by ykdt205 with SMTP id t205so43415631ykd.1 for ; Thu, 13 Aug 2015 08:00:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to:cc :content-type; bh=/Jyt6o4l1el0dSEh7zyHF0V1VEShYxiodCUM5YLNy5U=; b=FLko8aL6+jPLGCGT1zT2kkl4JKsfDbSyaF3iuE4fkobHV7/MNfxxoBppz368nL4uku yowdmDVZb4BTPcGiqh8TBoV4E6/GsCTFojVMlyQwUcWdjVCOW/LSH29o3/XyydiaqO3a +h9PrLntFhJMV2+aPiA6nXLFtowKo8kb7S1+wgk0nxjmBmZ7FxNQ0k5fH+WXj4OcpWzb KI7UH5BaB0/41c/Kg9346/B6JkPQC3NM89gNvqVUM2xamT36oN1GhIa0hBOLkNFI4bGp iLV/CJRvr5BbthQfL5AVMhUNMoYCIjU9VRIIScSVHC510GddQitWglFVR2ZfLM4LtEK5 h1kA== X-Gm-Message-State: ALoCoQkdKJLwi3SvaOdEYhrR+4JT0j8cqCaGcG8nNoWcu4jM0iLh/Tp9e4/F1UWpbY9Nd/T8vghK MIME-Version: 1.0 X-Received: by 10.170.150.7 with SMTP id r7mr40044745ykc.48.1439478001014; Thu, 13 Aug 2015 08:00:01 -0700 (PDT) Received: by 10.37.56.85 with HTTP; Thu, 13 Aug 2015 08:00:00 -0700 (PDT) X-Originating-IP: [78.147.11.89] Date: Thu, 13 Aug 2015 15:00:00 +0000 Message-ID: To: Christoph Becker Cc: "internals@lists.php.net" Content-Type: text/plain; charset=UTF-8 Subject: PCRE jit security hole WAS PCRE JIT stack size limit From: danack@basereality.com (Dan Ackroyd) On 23 July 2015 at 11:07, Christoph Becker wrote: > PHP7 supports PCRE's JIT compilation of patterns by default, which > mostly works fine. However, there are issues when the matching exceeds > the JIT stack limit, see bug #70110[1]. So to summarise and bring more people's attention to this conversation; the change to using pcre.jit does not seem to be a fantastic one. It allows preg_match to fail silently e.g. this code: preg_match('~(a)*~', str_repeat('a', 5431), $match); var_dump($match); gives the output: array(0) { } i.e. there is no notification that the preg_match failed to match. People use preg_match for black/white listing input for security purposes. As the input is under attacker control this seems like a very bad situation, as attackers will be able to figure out what input can be used to make those security checks give incorrect results silently. I don't think we should ship PHP 7 with this issue unresolved. A suggested fix for PHP 7.1 has been mentioned: > Instead I suggest to add > a new error constant which would be returned from preg_last_error(). I think this is a complete non-starter. It would be horrible to check after every call to preg_* whether or not the call succeeded. The regex engine failing is defintely way into the domain of exceptional circumstances, for which having an exception be thrown is the correct choice. I think we need to do either, or both, of the following for PHP 7: i) Ship PHP with pcre.jit=0 by default, and say that users should beware enabling it. ii) Within each preg_* function (or any other function) that calls PCRE check for PCRE_ERROR_JIT_STACKLIMIT and throw an exception if it is set. Other solutions involving switching between jit and non-jit have been discussed, but it looks like they won't be possible to implement in time for 7. Having function calls return bogus values without any warning is just a very bad idea, and I don't think PHP 7 should ship with that happening. cheers Dan p.s. with the ini setting of pcre.jit=0 the code does appear to fail-safe: > Now please consider the following simple expression > > preg_match('/^(foo)+$/', str_repeat('foo', $n)) > > This will fail (i.e. yield FALSE) independently of pcre.jit for large > enough $n. It doesn't actually return false, instead it segfaults for me. This is obviously not ideal, but at least the function doesn't silently return a bogus value.