Вопрос

While playing around with binary environment variables in Linux I found some strange behavior where it seems some single bytes were bad. I examined it closer and it seems that certain bytes will always be "converted" incorrectly when given to setenv(). Look at this:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    char array[256];

    int i;
    for(i = 1; i < 256; i++) {
        array[i] = i;
    }

    setenv("badenv", array, 1);

    system("/bin/sh");

    return 0;
}

I execute this program, then when I do echo $badenv > test; hexdump test I see:

0000000 0101 0302 0504 0706 2008 0c0b 0e0d 100f
0000010 1211 1413 1615 1817 1a19 1c1b 1e1d 201f
0000020 2221 2423 2625 2827 2a29 2c2b 2e2d 302f
0000030 3231 3433 3635 3837 3a39 3c3b 3e3d 403f

It seems that 0x9 is converted to 0x20, and that 0xa is converted to 0xb, among others.

Am I abusing setenv(), or maybe even I'm abusing environment variables in general? I've looked in the manpage and searched around some to see if environment variables should be able to handle binary values or not, but I'm not sure.

What is the cause of this behavior, is there any way around it, while still using environment variables?

Это было полезно?

Решение

The environment variable is split into "words" according to the value of $IFS, and the "words" are joined with a single separator - in this case an ordinary space. Thus the sequence "\x09\x0a", or "\t\n", is collapsed to one space ('\x20') when interpreting the contents of array.

IFS - The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is ''space tab newline''.

You can avoid the replacement by (temporarily) changing $IFS.

Note, however, that

  • array[0] has indeterminate value
  • array is not 0-terminated

in your programme. You should fix that.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top