Internet-Draft | I-Regexp | June 2023 |
Bormann & Bray | Expires 31 December 2023 | [Page] |
This document specifies I-Regexp, a flavor of regular expressions that is limited in scope with the goal of interoperation across many different regular-expression libraries.¶
This note is to be removed before publishing as an RFC.¶
Status information for this document may be found at https://datatracker.ietf.org/doc/draft-ietf-jsonpath-iregexp/.¶
Discussion of this document takes place on the JSONPath Working Group mailing list (mailto:[email protected]), which is archived at https://mailarchive.ietf.org/arch/browse/JSONPath/. Subscribe at https://www.ietf.org/mailman/listinfo/JSONPath/.¶
Source for this draft and an issue tracker can be found at https://github.com/ietf-wg-jsonpath/iregexp.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 31 December 2023.¶
Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
This specification describes an interoperable regular expression ("regexp") flavor, I-Regexp.¶
I-Regexp does not provide advanced regular expression features such as capture groups, lookahead, or backreferences. It supports only a Boolean matching capability, i.e., testing whether a given regular expression matches a given piece of text.¶
I-Regexp supports the entire repertoire of Unicode characters (Unicode scalar values); both the I-Regexp strings themselves and the strings they are matched against are sequences of Unicode scalar values (often represented in UTF-8 encoding form [STD63] for interchange).¶
I-Regexp is a subset of XSD regular expressions [XSD-2].¶
This document includes guidance for converting I-Regexps for use with several well-known regular expression idioms.¶
The development of I-Regexp was motivated by the work of the JSONPath Working Group. The Working Group wanted to include in its specification [I-D.ietf-jsonpath-base] support for the use of regular expressions in JSONPath filters, but was unable to find a useful specification for regular expressions which would be interoperable across the popular libraries.¶
This document uses the abbreviation "regexp" for what are usually called regular expressions in programming. "I-Regexp" is used as a noun meaning a character string (sequence of Unicode scalar values) that conforms to the requirements in this specification; the plural is "I-Regexps".¶
This specification uses Unicode terminology. A good entry point into that is provided by [UNICODE-GLOSSARY].¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
The grammatical rules in this document are to be interpreted as ABNF, as described in [RFC5234] and [RFC7405], where the "characters" of Section 2.3 of [RFC5234] are Unicode scalar values.¶
I-Regexps should handle the vast majority of practical cases where a matching regexp is needed in a data model specification or a query language expression.¶
The editors of this document conducted a survey of the regexp syntax used in published RFCs. All examples found there should be covered by I-Regexps, both syntactically and with their intended semantics. The exception is the use of multi-character escapes, for which workaround guidance is provided in Section 5.¶
An I-Regexp MUST conform to the ABNF specification in Figure 1.¶
As an additional restriction, charClassExpr
is not allowed to
match [^]
, which according to this grammar would parse as a
positive character class containing the single character ^
.¶
This is essentially XSD regexp without character class
subtraction, without multi-character escapes such as \s
,
\S
, and \w
, and without Unicode blocks.¶
An I-Regexp implementation MUST be a complete implementation of this limited subset. In particular, full support for the Unicode functionality defined in this specification is REQUIRED; the implementation MUST NOT limit itself to 7- or 8-bit character sets such as ASCII and MUST support the Unicode character property set in character classes.¶
A checking I-Regexp implementation is one that checks a supplied regexp for compliance with this specification and reports any problems. Checking implementations give their users confidence that they didn't accidentally insert non-interoperable syntax, so checking is RECOMMENDED. Exceptions to this rule may be made for low-effort implementations that map I-Regexp to another regexp library by simple steps such as performing the mapping operations discussed in Section 5; here, the effort needed to do full checking may dwarf the rest of the implementation effort. Implementations SHOULD document whether they are checking or not.¶
Specifications that employ I-Regexp may want to define in which cases their implementations can work with a non-checking I-Regexp implementation and when full checking is needed, possibly in the process of defining their own implementation classes.¶
This syntax is a subset of that of [XSD-2]. Implementations which interpret I-Regexps MUST yield Boolean results as specified in [XSD-2]. (See also Section 5.2.)¶
The material in this section is non-normative, provided as guidance to developers who want to use I-Regexps in the context of other regular expression dialects.¶
Common multi-character escapes (MCEs), and character classes built around them, which are not supported in I-Regexp, can usually be replaced as shown for example in Table 1.¶
MCE/class | Replace with |
---|---|
\S
|
[^ \t\n\r]
|
[\S ]
|
[^\t\n\r]
|
\d
|
[0-9]
|
Note that the semantics of \d
in XSD regular expressions is that of
\p{Nd}
; however, this would include all Unicode characters that are
digits in various writing systems, which is almost certainly not what is
required in IETF publications.¶
The construct \p{IsBasicLatin}
is essentially a reference to legacy
ASCII, it can be replaced by the character class [\u0000-\u007f]
.¶
Any I-Regexp also is an XSD Regexp [XSD-2], so the mapping is an identity function.¶
Note that a few errata for [XSD-2] have been fixed in [XSD11-2], which is therefore also included as a normative reference. XSD 1.1 is less widely implemented than XSD 1.0, and implementations of XSD 1.0 are likely to include these bugfixes, so for the intents and purposes of this specification an implementation of XSD 1.0 regexps is equivalent to an implementation of XSD 1.1 regexps.¶
Perform the following steps on an I-Regexp to obtain an ECMAScript regexp [ECMA-262]:¶
.
) outside character classes (first alternative
of charClass
production): replace dot by [^\n\r]
.¶
^(?:
and )$
.¶
The ECMAScript regexp is to be interpreted as a Unicode pattern ("u" flag; see Section 21.2.2 "Pattern Semantics" of [ECMA-262]).¶
Note that where a regexp literal is required,
the actual regexp needs to be enclosed in /
.¶
Perform the same steps as in Section 5.3 to obtain a valid regexp in PCRE [PCRE2], the Go programming language [RE2], and the Ruby programming language, except that the last step is:¶
\A(?:
and )\z
.¶
While regular expressions originally were intended to describe a formal language to support a Boolean matching function, they have been enhanced with parsing functions that support the extraction and replacement of arbitrary portions of the matched text. With this accretion of features, parsing regexp libraries have become more susceptible to bugs and surprising performance degradations which can be exploited in Denial of Service attacks by an attacker who controls the regexp submitted for processing. I-Regexp is designed to offer interoperability, and to be less vulnerable to such attacks, with the trade-off that its only function is to offer a boolean response as to whether a character sequence is matched by a regexp.¶
XSD regexps are relatively easy to implement or map to widely implemented parsing regexp dialects, with these notable exceptions:¶
\d
, \w
, \s
and their uppercase
complement classes exhibit a
large amount of variation between regexp flavors. Thus, they are
omitted from I-Regexp.¶
\p{Nd}
,
although the \p
/\P
feature in general is now quite
widely available. While in principle it is possible to
translate these into character-class matches, this also requires
access to those tables. Thus, regexp libraries in severely
constrained environments may not be able to support I-Regexp
conformance.¶
This document makes no requests of IANA.¶
While technically out of scope of this specification, Section 10 (Security Considerations) of [STD63] applies to implementations. Particular note needs to be taken of the last paragraph of Section 3 (UTF-8 definition) of [STD63]; an I-Regexp implementation may need to mitigate limitations of the platform implementation in this regard.¶
As discussed in Section 6, more complex regexp libraries may contain exploitable bugs leading to crashes and remote code execution. There is also the problem that such libraries often have hard-to-predict performance characteristics, leading to attacks that overload an implementation by matching against an expensive attacker-controlled regexp.¶
I-Regexps have been designed to allow implementation in a way that is resilient to both threats; this objective needs to be addressed throughout the implementation effort. Non-checking implementations (see Section 3.1) are likely to expose security limitations of any regexp engine they use, which may be less problematic if that engine has been built with security considerations in mind (e.g., [RE2]); a checking implementation is still RECOMMENDED.¶
Implementations that specifically implement the I-Regexp subset can, with care, be designed to generally run in linear time and space in the input, and to detect when that would not be the case (see below).¶
Existing regexp engines should be able to easily handle most I-Regexps (after the adjustments discussed in Section 5), but may consume excessive resources for some types of I-Regexps or outright reject them because they cannot guarantee efficient execution. (Note that different versions of the same regexp library may be more or less vulnerable to excessive resource consumption for these cases.)¶
Specifically, range quantifiers (as in a{2,4}
) provide particular
challenges for both existing and I-Regexp focused implementations.
These may therefore limit range quantifiers in composability
(disallowing nested range quantifiers such as (a{2,4}){2,4}
) or
range (disallowing very large ranges such as a{20,200000}
), or detect
and reject any excessive resource consumption caused by them.¶
I-Regexp implementations that are used to evaluate regexps from untrusted sources need to be robust to these cases. Implementers using existing regexp libraries are encouraged to check their documentation to see if mitigations are configurable, such as limits in resource consumption, and to document their own degree of robustness resulting from employing such mitigations.¶
This section is to be removed before publishing as an RFC.¶
This appendix contains a number of regular expressions that have been
extracted from some recently published RFCs based on some ad-hoc matching.
Multi-line constructions were not included.
With the exception of some (often surprisingly dubious) usage of multi-character
escapes and a reference to the IsBasicLatin
Unicode block, all
regular expressions validate against the ABNF in Figure 1.¶
This specification has been motivated by the discussion in the IETF JSONPATH
WG about whether to include a regexp mechanism into the JSONPath query
expression specification, as well as by previous discussions about the
YANG pattern
and CDDL .regexp
features.¶
The basic approach for this specification was inspired by The I-JSON Message Format [RFC7493].¶