Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:95784 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 8766 invoked from network); 8 Sep 2016 10:45:46 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 8 Sep 2016 10:45:46 -0000 Authentication-Results: pb1.pair.com header.from=yohgaki@ohgaki.net; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=yohgaki@ohgaki.net; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain ohgaki.net designates 180.42.98.130 as permitted sender) X-PHP-List-Original-Sender: yohgaki@ohgaki.net X-Host-Fingerprint: 180.42.98.130 ns1.es-i.jp Received: from [180.42.98.130] ([180.42.98.130:57537] helo=es-i.jp) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 11/56-36123-75141D75 for ; Thu, 08 Sep 2016 06:45:46 -0400 Received: (qmail 32204 invoked by uid 89); 8 Sep 2016 10:45:40 -0000 Received: from unknown (HELO mail-qk0-f177.google.com) (yohgaki@ohgaki.net@209.85.220.177) by 0 with ESMTPA; 8 Sep 2016 10:45:40 -0000 Received: by mail-qk0-f177.google.com with SMTP id v123so42930800qkh.2 for ; Thu, 08 Sep 2016 03:45:40 -0700 (PDT) X-Gm-Message-State: AE9vXwPb0LVmKKggScESCLVYV8L6n/fKxd4MeVgg7HbVv5pRK9rMPR+6tBL7nYiXnnLBtz3U2fA7I/0xgP9s/w== X-Received: by 10.55.153.68 with SMTP id b65mr58636817qke.10.1473331533852; Thu, 08 Sep 2016 03:45:33 -0700 (PDT) MIME-Version: 1.0 Received: by 10.140.84.168 with HTTP; Thu, 8 Sep 2016 03:44:52 -0700 (PDT) In-Reply-To: References: <232F1604-2211-4351-B830-EDC958A25D6D@strojny.net> <2de35db0-9974-cc96-83dd-3d2dbd48f7f8@lsces.co.uk> <5b72e9da-068a-bc79-82c2-f36f723f42bb@gmail.com> Date: Thu, 8 Sep 2016 19:44:52 +0900 X-Gmail-Original-Message-ID: Message-ID: To: Rowan Collins Cc: "internals@lists.php.net" Content-Type: text/plain; charset=UTF-8 Subject: Re: [PHP-DEV] [RFC][VOTE] Add validation functions to filter module From: yohgaki@ohgaki.net (Yasuo Ohgaki) Hi Rowan, On Thu, Sep 8, 2016 at 6:02 PM, Rowan Collins wrote: > On 08/09/2016 09:28, Yasuo Ohgaki wrote: >> >> This might be the largest difference. >> >> To make something secure than it is now, adding additional security >> layer is effective, not single location/code. > > > My instinct is that this extra location would be a maintenance nightmare, as > it would need to keep up with changes elsewhere in the application. In day > to day use, what would make this extra security layer any more likely to be > comprehensively maintained than the existing validation layer? You are right and wrong. WAF(Web application firewall) maintenance that is customized for certain app is nightmare, I fully agree. Dividing input validations and logic checks works. These two are focusing on different objectives, format and logic. Finding programmer's mistakes is a lot easier with software built-in input validation, unlike WAF, because programmer knew what's the inputs. UNIT tests help also. That's the reasons why it works much better than WAF approach. > > >> Suppose we have validation module. You are suggesting something like >> >> $int = validate_int($var, $min, $max); >> $bool = validate_bool($var, $allowed_bool_types); >> // i.e. which type of bool 1/0, yes/no, on/off, true/false is allowed >> // This isn't implemented. All of them are valid bools currently. >> $str = validate_string($var, $min_len, $max_len); >> $str = validate_string_encoding($var, $encoding); >> $str = validate_string_chars($var, $allowed_chars); >> $str = validate_string_regex($var, $regex); >> $str = validate_string_degit($var, $min_len, $max_len); >> $str = validate_string_callback($var, $callback); > > > No, I'm suggesting something like: > > if ( > ! validate_int($var, $min, $max) > || ! validate_bool($var, $allowed_bool_types) > || ! validate_string($var, $min_len, $max_len) > || ! validate_string_encoding($var, $encoding) > || ! validate_string_chars($var, $allowed_chars) > || ! validate_string_regex($var, $regex) > || ! validate_string_degit($var, $min_len, $max_len) > || ! $callback($var) // Note: no need to wrap this callback, it's > just a boolean-returning function > ) > { > // ERROR > } My opinion is "it's better to separate this kind of _required_ format check from logic" to make logic simpler and more maintainable. Think of this format check as "forcing types". Even if you force DATE type, you still might have to check logical errors in logic(model). e.g. Reservation date for a service can only be set within certain range. If you're on the same boat as me. You don't have to return anything, but catch exception. Above code would be $validate_my_var, 'some_var' => $validate_some_var, 'another_var' => $validate_another_var, ]; function validate_array($input, $definition) { foreach($definition as $key => $func) { // Cannot handle "optional" rule well with this code. $func($input[$key]); } } try { validate_array($_POST, $validation_def); } catch (InputValidationException $e) { // cleanup and die } ?> It seems a lot like proposed code with a lot more typing. IMO. However, I'm OK with this kind of implementation, too. i.e. Providing basic validate_*() functions. Half implemented filter module validator problem remains, though. > > It was a deliberately narrow purpose as an example, but IMHO that's > perfectly readable, and the focus of the module would be on creating a good > set of validation rules, rather than worrying about how they're applied. > > >> [...] Rule reuse and centralizing validation rule is easy. > > > The language provides us plenty of ways to reuse code. For instance: > > function validate_my_field($var) { > return > validate_int($var, $min, $max) > && validate_bool($var, $allowed_bool_types) > // etc OK. I understood you prefer simple validation functions solution. PHP is generic programming language, so most features could be implemented by basic constructs. Code reuse works with simple functions. However, how about definition reuse? It cannot be reused easily to generate JavaScript validation code, for example. If example code made definition reusable, it would look more like proposed code. We have working filter, and half implemented validator by filter module. Leaving it as it is now is not good, IMHO. Why not finish validator implementation and provide ready to use tool? Resulting code would be similar to simple validation functions implementation, somewhat at least, anyway. What filter module is missing as validator currently are: - Whitelisting concept (Implemented) - Multiple rules for a variable (Implemented) - String rules (Implemented) - Optional rule (To be implemented. Refactoring is needed) My PR implements above 3 out of 4 mandatory features to filter module validation. I still fail to see what's wrong for improving/finishing filter module implementation and what's wrong in my improvement proposal. Suggestions are appreciated always! Regards, -- Yasuo Ohgaki yohgaki@ohgaki.net