A comparação de expressão regular Bash falha para byte hexadecimal \ x01

4

A expressão regular de Bash falha na comparação correta para $'\x01' quando é usado o caractere de fim de seqüência de caracteres char $ . Todos os outros valores de byte (parecem) se comparam corretamente.

Usando o GNU bash 4.1.5 (1). Isso é um bug ou existe outra maneira de representar bytes em notação hexadecimal, além de $'\...' ? ... Mas não parece ser a notação, porque até mesmo um caracter literal para comparação literal de caracteres falha.

Esta 'falha' só acontece quando o $'\x01' precede imediatamente o Fim-de-String $ .

Aqui estão alguns exemplos:

echo 'non \x01 with ^ and $'
[[      3  =~ ^$'\x33'$ ]]; echo $?  # 0 
[[      3  =~ ^$'3'$ ]]; echo $?  # 0 
[[ $'\x12' =~ ^$'\x12'$ ]]; echo $?  # 0 
[[ $'
echo 'non \x01 with ^ and $'
[[      3  =~ ^$'\x33'$ ]]; echo $?  # 0 
[[      3  =~ ^$'3'$ ]]; echo $?  # 0 
[[ $'\x12' =~ ^$'\x12'$ ]]; echo $?  # 0 
[[ $'%pre%2' =~ ^$'\x02'$ ]]; echo $?  # 0 

echo '\x01 with no ^ or $'
[[ $'\x01' =~  $'\x01'  ]]; echo $?  # 0 
[[ $'\x01' =~  $'%pre%1'  ]]; echo $?  # 0 
[[       =~  $'%pre%1'  ]]; echo $?  # 0   nb. Literal char does not render
[[       =~         ]]; echo $?  # 0   nb. Literal char does not render

echo '\x01 with ^ only'
[[ $'\x01' =~ ^$'\x01'  ]]; echo $?  # 0 
[[ $'\x01' =~ ^$'%pre%1'  ]]; echo $?  # 0 
[[       =~ ^$'%pre%1'  ]]; echo $?  # 0   nb. Literal char does not render
[[       =~ ^       ]]; echo $?  # 0   nb. Literal char does not render

echo '\x01 with ^ and $'
[[ $'\x01' =~ ^$'\x01'$ ]]; echo $?  # 1 
[[ $'\x01' =~ ^$'%pre%1'$ ]]; echo $?  # 1 
[[       =~ ^$'%pre%1'$ ]]; echo $?  # 1   nb. Literal char does not render
[[       =~ ^$      ]]; echo $?  # 1   nb. Literal char does not render

echo '\x01 with $ only'
[[ $'\x01' =~  $'\x01'$ ]]; echo $?  # 1 
[[ $'\x01' =~  $'%pre%1'$ ]]; echo $?  # 1 
[[       =~  $'%pre%1'$ ]]; echo $?  # 1   nb. Literal char does not render
[[       =~  $      ]]; echo $?  # 1   nb. Literal char does not render

echo '\x01 with $ only, but not adjacent to \x01'
[[ $'\x01'c =~  $'\x01'c$ ]]; echo $?  # 0 
[[ $'\x01'c =~  $'%pre%1'c$ ]]; echo $?  # 0 
[[      c =~  $'%pre%1'c$ ]]; echo $?  # 0   nb. Literal char does not render
[[      c =~  c$      ]]; echo $?  # 0   nb. Literal char does not render
2' =~ ^$'\x02'$ ]]; echo $? # 0 echo '\x01 with no ^ or $' [[ $'\x01' =~ $'\x01' ]]; echo $? # 0 [[ $'\x01' =~ $'%pre%1' ]]; echo $? # 0 [[ =~ $'%pre%1' ]]; echo $? # 0 nb. Literal char does not render [[ =~ ]]; echo $? # 0 nb. Literal char does not render echo '\x01 with ^ only' [[ $'\x01' =~ ^$'\x01' ]]; echo $? # 0 [[ $'\x01' =~ ^$'%pre%1' ]]; echo $? # 0 [[ =~ ^$'%pre%1' ]]; echo $? # 0 nb. Literal char does not render [[ =~ ^ ]]; echo $? # 0 nb. Literal char does not render echo '\x01 with ^ and $' [[ $'\x01' =~ ^$'\x01'$ ]]; echo $? # 1 [[ $'\x01' =~ ^$'%pre%1'$ ]]; echo $? # 1 [[ =~ ^$'%pre%1'$ ]]; echo $? # 1 nb. Literal char does not render [[ =~ ^$ ]]; echo $? # 1 nb. Literal char does not render echo '\x01 with $ only' [[ $'\x01' =~ $'\x01'$ ]]; echo $? # 1 [[ $'\x01' =~ $'%pre%1'$ ]]; echo $? # 1 [[ =~ $'%pre%1'$ ]]; echo $? # 1 nb. Literal char does not render [[ =~ $ ]]; echo $? # 1 nb. Literal char does not render echo '\x01 with $ only, but not adjacent to \x01' [[ $'\x01'c =~ $'\x01'c$ ]]; echo $? # 0 [[ $'\x01'c =~ $'%pre%1'c$ ]]; echo $? # 0 [[ c =~ $'%pre%1'c$ ]]; echo $? # 0 nb. Literal char does not render [[ c =~ c$ ]]; echo $? # 0 nb. Literal char does not render
    
por Peter.O 08.04.2015 / 18:22

1 resposta

2

Sim, foi um bug em versões antigas do bash corrigido no bash-4.2.14

E aqui está o commit que faz o problema desaparecer ; faça do que você quiser.

O que é CTLESC ? Está definido em syntax.h as #define CTLESC '\x011' , veja você. É algum tipo de fuga interna de alguma forma envolvida na expansão. Parece que o erro pode ser que o seu CTLESC data está sendo interpretado como se fosse um %code% gerado internamente ou algo assim.

commit 25db9a70d4c2ba5c43d4167f231bdd8d760d5a06
Author: Chet Ramey <[email protected]>
Date:   Tue Nov 22 20:02:46 2011 -0500

    Bash-4.2 patch 14

diff --git a/patchlevel.h b/patchlevel.h
index 636be1c..04b423b 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
    regexp '^#define[   ]*PATCHLEVEL', since that's what support/mkversion.sh
    looks for to find the patch level (for the sccs version string). */

-#define PATCHLEVEL 13
+#define PATCHLEVEL 14

 #endif /* _PATCHLEVEL_H_ */
diff --git a/pathexp.c b/pathexp.c
index 42f21e4..f239956 100644
--- a/pathexp.c
+++ b/pathexp.c
@@ -196,7 +196,7 @@ quote_string_for_globbing (pathname, qflags)
    {
      if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
        continue;
-     if ((qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
+     if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
        continue;
      temp[j++] = '\';
      i++;
    
por 04.08.2017 / 12:03