¿Por qué obtengo un resultado inesperado al intentar realizar un bucle para determinar la cantidad de veces ingresadas por el usuario?

¿Por qué obtengo un resultado inesperado al intentar realizar un bucle para determinar la cantidad de veces ingresadas por el usuario?

Estoy escribiendo este script de bash shell:

#!/bin/bash

declare -i N
read N
for i in {1..$N}
do
  echo "Number: $i"
done

(Creo que declare -i Nhace que sea Nun número entero)

Sin embargo, al ejecutar esto, obtengo el siguiente resultado:

>vim new.sh
>chmod +x passgen.sh
>./passgen.sh
15
Number: {1..15}

Aquí quiero tomar el límite del usuario y luego ejecutar el bucle.

Respuesta1

De man bash:

El orden de las expansiones es: expansión de llaves; expansión de tilde, expansión de parámetros y variables, expansión aritmética y sustitución de comandos (realizada de izquierda a derecha); división de palabras; y expansión del nombre de ruta.

Como puede ver, la expansión de la llave es lo primero, por lo que aparentemente se omite en su problema. En su lugar, usaría un bucle diferente.

Respuesta2

Si bien ya se ha señalado el problema con la expansión de llaves, solo comentaré:

(Creo que declarar -i N hace que N sea un número entero)

Responderé que sí, lo hace, y es un problema ya que lo convierte en una vulnerabilidad de inyección de comandos. Con ese atributo de número entero establecido, siempre que a la variable se le asigna un valor, ese valor se interpreta como una expresión aritmética.

Si el usuario ingresa a[$(reboot)]en ese readmensaje, eso provocará un intento de reinicio, por ejemplo.

Ese es un problema general con bashy zshsiempre kshque se evalúan expresiones aritméticas. Incluso usar la for (( i = 1; i <= N; i++ ))forma de estilo ksh93 (con o sin declare -i N) sería un problema ya que el contenido de Ntodavía se evalúa en ese contexto aritmético.

for i in {1..$N}estaría bien (sin declare -i N) en ksh, zsh o yash -o braceexpand(se repetiría un galimatías pero no introduciría una vulnerabilidad de inyección de comandos), o podría usar shla sintaxis estándar siempre que su shimplementación no se base en ksh.

#! /bin/sh -
IFS= read -r N
i=1; while [ "$i" -lt "$N" ]; do
  printf '%s\n' "Number: $n"
done

kshTodavía [trata el operando -ltcomo expresiones aritméticas, por lo que aún introduciría vulnerabilidades de inyección de comandos. No utilice [[ $i -lt $N ]]ni (( i < N ))en bash// zshque kshtambién tengan el problema.

O podría usar awk/ perlo cualquier lenguaje de programación adecuado para realizar el ciclo, o podría desinfectar primero la entrada.

información relacionada