Нашёл нынче совершенно случайно багу в нашем коммерческом продукте. Офигел слегка.
Нашёл нынче совершенно случайно багу в нашем коммерческом продукте. Офигел слегка.
Бага заключается в следующем: утилита, если ей задать один параметр и не задать другой (второй к первому обязателен, а я не знал) ругается (что параметра нет) и внезапно молча удаляет конфигурационный файл. После чего все эта утилита работать не хочет, потому что конфигурационного файла нет, а значит, ничего нет. Я как-то не сразу понял, в чём дело, но потом разобрался, как именно это воспроизвести и даже почему это так происходит (для коллег -- PCLIN-29569).
Код примерно вот такой:
int SomeFunction(int id, int cmd)
...
char dumpfile[4096];
...
if (gparam->dumpfile == NULL) {
if (cmd == CMD_DUMP) {
logger(-1, 0, "Dump file is not specified.");
goto child_err;
}
...
// где-то тут мы заносим имя файла в dumpfile, но до этого места мы не доходим.
...
child_err:
if (cmd == CMD_CHKPNT || cmd == CMD_DUMP)
unlink(gparam->dumpfile ? : dumpfile);
Похоже, что dumpfile выделяется на стеке, и в этом же самом месте памяти раньше лежало имя файла, который мы и удаляем. И компилятор, конечно, не может поругаться на неинициализированную переменную -- мало ли куда какой поинтер передают...
На закуску любителям языка Си -- угадайте, что напечатает этот код (ну или так -- что он может напечатать, согласно стандарту и на практике):
#include <stdio.h>
void a(void) {
char str[32];
sprintf(str, "My father was a sailor");
}
void b(void) {
char str[16];
puts(str);
}
int main(void) {
a(); b();
return 0;
}
Ответ чёрным по чёрному (выделите мышкой, чтобы увидеть):
Всё что угодно может напечатать; у меня с gcc-4.5.1 -O0 он печатает слово sailor :)
спасити-памагити.
Всем, кто в той или иной мере недоволен коллективом, в котором работает, информация к размышлению: инженер Игорь Авербух потравил коллег, как тараканов.
Всё, как говорится, познается в сравнении.
В интернетах эта функция гуглится, но то, что нагугливается. не работает под dash. Ввиду того, что дебианеры фашисты в Debian шеллом по умолчанию может запросто оказаться dash, а городить зависимость от bash не хочется, я слегка переделал скопипащенную из интернетов функцию, и теперь она работает и под dash тоже.
Покритикуйте, кто в теме.
cidr2mask() {
local i mask=""
local full_octets=$(($1/8))
local partial_octet=$(($1%8))
for i in 0 1 2 3; do
if [ $i -lt $full_octets ]; then
mask="${mask}255"
elif [ $i -eq $full_octets ]; then
mask="${mask}$((256 - (1 << (8 - $partial_octet))))"
else
mask="${mask}0"
fi
test $i -lt 3 && mask="${mask}."
done
echo $mask
}