From 7d2a21669416264cac84fa8600852649a471c6e8 Mon Sep 17 00:00:00 2001 From: Bruno Le Floch Date: Wed, 27 Feb 2019 15:31:29 +0100 Subject: [PATCH] Make \IfBooleanTF safer (check its argument is true or false) --- l3packages/CHANGELOG.md | 7 ++++++- l3packages/xparse/xparse.dtx | 35 +++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/l3packages/CHANGELOG.md b/l3packages/CHANGELOG.md index 71a74c69f4..4acebeb661 100644 --- a/l3packages/CHANGELOG.md +++ b/l3packages/CHANGELOG.md @@ -6,7 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), this project uses date-based 'snapshot' version identifiers. ## [Unreleased] -- `xparse`: implement b-type argument to grab body of environments + +### Added +- `xparse`: b-type argument to grab body of environments + +### Changed +- `xparse`: make \IfBooleanTF safer ## [2018-09-24] diff --git a/l3packages/xparse/xparse.dtx b/l3packages/xparse/xparse.dtx index 9add4492da..bc0919408f 100644 --- a/l3packages/xparse/xparse.dtx +++ b/l3packages/xparse/xparse.dtx @@ -4652,19 +4652,34 @@ % % \begin{macro}{\IfBooleanT, \IfBooleanF, \IfBooleanTF} % The logical \meta{true} and \meta{false} statements are just the -% normal \cs{c_true_bool} and \cs{c_false_bool}, so testing for them is -% done with the \cs{bool_if:NTF} functions from \textsf{l3prg}. +% normal \cs{c_true_bool} and \cs{c_false_bool} so \cs{bool_if:NTF} is +% almost enough. However, this code-level function blows up badly +% when passed invalid input. We want \cs{IfBooleanTF} to accept a +% single (non-space) token equal to \cs{c_true_bool} or +% \cs{c_false_bool}, possibly surrounded by spaces. If the input is +% blank or multiple items, jump to the error and pick the false +% branch. If the input, ignoring spaces (we do this by omitting +% braces in the \cs{tl_if_single_token:nF} test), is not a single +% token then jump to the error as well. It is then safe to compare +% the token to the two booleans, picking the appropriate branch. If +% neither matches, we jump to the error as well. % \begin{macrocode} \cs_new:Npn \IfBooleanTF #1 { - \bool_lazy_and:nnTF - { \tl_if_single_p:n {#1} } - { \tl_if_single_token_p:n #1 } - { \bool_if:NTF #1 } - { - \__kernel_msg_error:nnn { xparse } { if-boolean } {#1} - \use_ii:nn - } + \tl_if_single:nF {#1} + { \prg_break:n { \use:n } } + \tl_if_single_token:nF #1 + { \prg_break:n { \use:n } } + \token_if_eq_meaning:NNT #1 \c_true_bool + { \prg_break:n { \use_ii:nnn } } + \token_if_eq_meaning:NNT #1 \c_false_bool + { \prg_break:n { \use_iii:nnn } } + \prg_break:n { \use:n } + \prg_break_point: + { + \__kernel_msg_error:nnn { xparse } { if-boolean } {#1} + \use_ii:nn + } } \cs_new:Npn \IfBooleanT #1#2 { \IfBooleanTF {#1} {#2} { } } \cs_new:Npn \IfBooleanF #1 { \IfBooleanTF {#1} { } }