Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What causes `awk` to inject an extra '0' when embedding a shell variable incorrectly?

Tags:

bash

shell

awk

I have already seen this question and I now know how to pass shell variables correctly to awk.

However, I noticed a curious behavior in my initial incorrect attempts:

ip=10.170.115.13

echo $ip
10.170.115.13

echo foo | awk "{print ${ip} }"
10.170.1150.13

Observe the extra 0 in the output above.

Is this undefined behavior, or is there a logical reason why the 0 appears where it does?

Here is my awk version:

awk --version
awk version 20200816

This also happens with gawk:

gawk --version
GNU Awk 5.3.1, API 4.0, (GNU MPFR 4.2.1, GNU MP 6.3.0)
Copyright (C) 1989, 1991-2024 Free Software Foundation.
like image 645
merlin2011 Avatar asked Sep 11 '26 08:09

merlin2011


2 Answers

When the variable is substituted into the script, it looks like

awk "{print 10.170.115.13 }"

Since there are no quotes around the IP, awk tries to parse it as numbers, not a string.

I think it's actually being parsed as 3 numbers: 10.170, .115, and .13. The extra 0 comes from the default format for printing floating point numbers, which always includes a digit before the decimal point; .13 gets printed as 0.13. .115 also becomes 0.115, but we don't get an extra zero there because 10.170 becomes 10.17 (since trailing zeroes after the decimal are discarded).

The right solution is to use the -v option to convert the shell variable to an awk variable. To fix it with your variable substitution method you need to add literal quotes so it will be parsed as a string.

awk "{print \"$ip\" }"
like image 170
Barmar Avatar answered Sep 14 '26 07:09

Barmar


This has nothing to do with injection itself, observe that

echo foo | awk '{print 10.170.115.13}'

gives output

10.170.1150.13

Observe that it will also happen for 3 dots

echo foo | awk '{print 10.171.115}'

gives output

10.1710.115

I suspect GNU AWK tokenizer does detect 2 numbers, for 10.171.115 it is 10.171 and .115 (certain way of writing 0.115) and then normalize them (see OFMT) and then concatenate them as empty string is treated as concatenate operator (e.g. like in print $1$2). Further research of tokenizer of GNU AWK is required in order to prove or deny this hypothesis, but I do not have enough knowledge to do that.

like image 43
Daweo Avatar answered Sep 14 '26 07:09

Daweo