0

I am writing this bash shell script:

#!/bin/bash

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

(I believe declare -i N makes the N an integer)

However on running this, I get the following output:

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

Here I want to take the limit from user, and then run the loop.

2 Answers2

0

From man bash:

The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion.

As you can see brace expansion is first, so apparently it is skipped in your problem. I'd use a different loop instead.

0

While the problem with brace expansion has already been pointed out, I'll just comment on:

(I believe declare -i N makes the N an integer)

I'll answer, yes, it does, and it's a problem as it makes it an command injection vulnerability. With that integer attribute set, whenever the variable is assigned a value, that value is interpreted as an arithmetic expression.

If the user enters a[$(reboot)] at that read prompt, that will cause a reboot attempt for instance.

That's a general problem with bash, zsh and ksh whenever arithmetic expressions are evaluated. Even using the for (( i = 1; i <= N; i++ )) ksh93-style form (with or without declare -i N) would be a problem as the contents of N is still evaluated in that arithmetic context.

for i in {1..$N} would be fine (without declare -i N) in ksh, zsh or yash -o braceexpand (would loop on gibberish but not introduce a command injection vulnerability), or you could use standard sh syntax provided your sh implementation is not based on ksh.

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

ksh's [ still treats operand of -lt as arithmetic expressions, so would still introduce command injection vulnerabilities. Do not use [[ $i -lt $N ]] or (( i < N )) in bash/zsh/ksh which also have the problem.

Or you could use awk / perl or any proper programming language to do the loop, or you could first sanitise the input.