From 2ccd2cad1955accc1b376bc1226337988f516926 Mon Sep 17 00:00:00 2001 From: Ovid Date: Fri, 3 Jan 2025 11:44:52 +0100 Subject: [PATCH 1/4] First draft of PPC 0032: Optional Strictures and Warnings --- ppcs/ppc0032-optional-strictures.md | 170 ++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 ppcs/ppc0032-optional-strictures.md diff --git a/ppcs/ppc0032-optional-strictures.md b/ppcs/ppc0032-optional-strictures.md new file mode 100644 index 0000000..046b415 --- /dev/null +++ b/ppcs/ppc0032-optional-strictures.md @@ -0,0 +1,170 @@ +# Adding Optional Strictures and Warnings Classifications to Perl + +## Preamble + + Author: Curtis "Ovid" Poe + Sponsor: + ID: 0032 + Status: Draft + +## Abstract + +This PPC proposes adding mechanisms for optional strictures and warnings to +Perl that would not be enabled by the standard `use strict` and `use warnings` +pragmas. This allows for introducing new strict checks and warnings without +affecting existing code that uses these pragmas. As a concrete example, this +PPC proposes adding `use strict 'strings'` as the first such optional +stricture, which would prevent implicit stringification of references, similar +to the functionality provided by the CPAN module `stringification`. + +## Motivation + +The current `strict` and `warnings` pragmas in Perl effectively enable all +available strictures and warnings when used in their recommended forms (`use +strict` and `use warnings`). This creates a challenge when wanting to +introduce new strict checks or warnings that might be too strict or noisy for +general use but valuable for specific cases. Currently, such functionality +must be implemented as separate pragmatic modules (like `indirect`, +`multidimensional`, or `bareword::filehandles`), leading to inconsistent +interfaces and documentation scattered across different locations. + +The specific case of implicit reference stringification illustrates this +problem well. When references are implicitly stringified (e.g., `"$ref"`), +they produce output like `ARRAY(0x1234567)` which is rarely useful and often +indicates a programming error. However, this behavior cannot be prohibited +under the current `strict` pragma as it would break existing code. + +## Rationale + +Adding support for optional strictures and warnings provides several benefits: + +1. It allows for introducing new strict checks and warnings without breaking + backward compatibility +2. It provides a consistent interface for enabling such checks (`use strict + 'feature'` rather than `no feature`) +3. It groups related functionality under the established `strict` and + `warnings` pragmas +4. It provides a clear path for experimental features to graduate into core + Perl + +The stringification case demonstrates these benefits. Rather than using a +separate `no stringification` pragma, the functionality can be enabled with +`use strict 'strings'`, which is more consistent with existing Perl syntax and +more discoverable through the standard documentation. + +## Specification + +### Optional Strictures + +Add support for optional strict modes that are not enabled by a bare `use +strict` statement. These would be enabled explicitly: + +```perl +use strict 'strings'; # Enable reference stringification checks +``` + +The first such optional stricture would be 'strings', which prevents implicit +stringification of references. When enabled, the following operations would +die with an error if attempted on a non-object reference: + +- String interpolation (`"$ref"`) +- String concatenation (`$ref . "foo"`) +- Case conversion (`lc`, `lcfirst`, `uc`, `ucfirst`) +- Pattern matching (`$ref =~ m//`) +- String operations (`split`, `join`) +- Output operations (`print`, `say`) + +Error messages would be specific to the operation being performed, e.g.: + +``` +Attempted to stringify a reference at line X +Attempted to concat a reference at line Y +``` + +### Optional Warnings + +Add a new warnings classification for optional warnings that are not +enabled by `use warnings` or `use warnings 'all'`. These would require +explicit enabling: + +```perl +use warnings 'optional'; # Enable all optional warnings +use warnings 'optional::specific'; # Enable specific optional warning +``` + +## Backwards Compatibility + +This proposal is explicitly designed to maintain backward compatibility: + +- Existing code using `use strict` or `use warnings` will continue to work + unchanged +- New strictures and warnings must be explicitly enabled +- The mechanism allows for gradual adoption of new features +- Existing modules like `stringification` can be updated to use the new + mechanism while maintaining their current interface + +## Security Implications + +The proposed changes improve security by allowing developers to catch more +potential programming errors. The stringification case in particular can help +prevent information leaks where reference addresses might be accidentally +exposed in output. + +## Examples + +Here's a trivial example: + +```perl +use strict 'all', 'strings'; +use warnings; + +my $data = [ sensitive_info() ]; +log("Processing $data"); # Dies +``` + +## Prototype Implementation + +The [`stringification` module on +CPAN](https://metacpan.org/release/PEVANS/stringification-0.01_004/view/lib/stringification.pm) +provides a prototype for the reference stringification checks. The +implementation can be adapted to work as a core feature, using similar +op-hooking techniques. + +## Future Scope + +1. Additional optional strictures could include: + - `strict 'direct'` (current `indirect` module) + - `strict 'filehandles'` (current `bareword::filehandles` feature) + +2. Warning modes for optional strictures: + - `use strict 'strings=warn'` to warn rather than die + +## Rejected Ideas + +1. Adding new strictures to the default `strict` mode: + - Would break backward compatibility + - Would make `strict` too restrictive for general use + +2. Using negative pragmas (`no feature`): + - Less consistent with Perl's existing pragma system + - Makes features harder to discover + +## Open Issues + +1. Should optional strictures be combinable with core strictures in a single statement? + + ```perl + use strict qw(vars refs subs strings); # vs separate statements + ``` + +2. Should there be a way to enable all optional strictures at once? + + ```perl + use strict 'optional'; # ? + ``` + +## Copyright + +Copyright (C) 2025, Curtis "Ovid" Poe. + +This document and code and documentation within it may be used, redistributed and/or modified under the same terms as Perl itself. From ca12004d49ea8694709343b724693329f2acb7ed Mon Sep 17 00:00:00 2001 From: Ovid Date: Fri, 3 Jan 2025 12:01:05 +0100 Subject: [PATCH 2/4] Extended the "Open Issues" section. --- ppcs/ppc0032-optional-strictures.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ppcs/ppc0032-optional-strictures.md b/ppcs/ppc0032-optional-strictures.md index 046b415..01a07eb 100644 --- a/ppcs/ppc0032-optional-strictures.md +++ b/ppcs/ppc0032-optional-strictures.md @@ -151,18 +151,23 @@ op-hooking techniques. ## Open Issues -1. Should optional strictures be combinable with core strictures in a single statement? +1. The PPC specifically mentions "non-object" stringification. Should this be + more general and apply to all references? - ```perl - use strict qw(vars refs subs strings); # vs separate statements - ``` +2. How should string overloading be handled? Presumably, stringification + should be allowed for objects that overload stringification. Hence, the + earlier restriction on "non-object" stringification, but it's unclear if + that's the best approach. -2. Should there be a way to enable all optional strictures at once? +3. Should there be a way to enable all optional strictures at once? ```perl use strict 'optional'; # ? ``` +See also [Grinnz's feature suggestion on this +matter](https://github.com/Perl/perl5/issues/18543). + ## Copyright Copyright (C) 2025, Curtis "Ovid" Poe. From 12a5f465fbfc2c7a836d184a947661228a55182c Mon Sep 17 00:00:00 2001 From: Ovid Date: Fri, 3 Jan 2025 12:06:23 +0100 Subject: [PATCH 3/4] Update "Security" section. --- ppcs/ppc0032-optional-strictures.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ppcs/ppc0032-optional-strictures.md b/ppcs/ppc0032-optional-strictures.md index 01a07eb..ba915bd 100644 --- a/ppcs/ppc0032-optional-strictures.md +++ b/ppcs/ppc0032-optional-strictures.md @@ -108,7 +108,8 @@ This proposal is explicitly designed to maintain backward compatibility: The proposed changes improve security by allowing developers to catch more potential programming errors. The stringification case in particular can help prevent information leaks where reference addresses might be accidentally -exposed in output. +exposed in output, though that seems unlikely to be a significant security +issue. ## Examples From ab636dcb442baecabe76c549457216180a16a781 Mon Sep 17 00:00:00 2001 From: Ovid Date: Fri, 3 Jan 2025 12:27:43 +0100 Subject: [PATCH 4/4] Fix the syntax in our "strict" example. --- ppcs/ppc0032-optional-strictures.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ppcs/ppc0032-optional-strictures.md b/ppcs/ppc0032-optional-strictures.md index ba915bd..7adc548 100644 --- a/ppcs/ppc0032-optional-strictures.md +++ b/ppcs/ppc0032-optional-strictures.md @@ -116,13 +116,21 @@ issue. Here's a trivial example: ```perl -use strict 'all', 'strings'; +use strict 'refs', 'subs, 'vars', 'strings'; use warnings; my $data = [ sensitive_info() ]; log("Processing $data"); # Dies ``` +Perhaps a new `strict` flag, `strict 'standard'`, could enable the combined +'refs', 'subs', and 'vars' strictures to make it easier to enable them with +optional strictures: + +```perl +use strict 'standard', 'strings'; +``` + ## Prototype Implementation The [`stringification` module on