← Bilinen Hatalar

mkconfigs: Ham Satır Sonlarıyla Geçersiz C String'i Üretiyordu

BusyBox Kod Üretici Aracı 1779 commit etkilendi 2005-08-01 → 2006-10-05

Ne Oldu ve Neden

Bu, bu projede bulduğumuz en uzun süren (14 ay, ~1780 commit) gerçek BusyBox hatası. "bbconfig" applet'i kullanıcının o anki .config'unu çalışan binary içine gömüp busybox --show-config gibi bir komutla gösterebilmek için scripts/config/mkconfigs.c adlı bir C programı yazıldı. Bu program derleme sırasında .config'i okuyup her satırı doğrudan bir C string literal'i içine fprintf ile basıyordu — satır sonu karakterlerini \n olarak kaçışlamadan, ham (raw) newline olarak.

Sonuç: include/bbconfigopts.h içinde 900+ satır boyunca tek bir "..." string literal'i, ortasında yüzlerce kaçışsız satır sonu ile. Bu hiçbir C standardında geçerli değil — gerçek bir derleyiciye verilseydi "missing terminating " character" hatası alırdın (tıpkı bu projede bulduğumuz başka bir 1999 hatasında olduğu gibi). BusyBox'ın kendi basit bağımlılık tarayıcısı scripts/bb_mkdep.c bunu farklı şekilde ama yine başarısız olarak işliyor, "hmm, unterminated" diyerek build'i durduruyordu — ve bu dosya make .depend adımında HER build'de koşulsuz üretildiği için, bu dönemdeki hemen hemen hiçbir commit build edilemiyordu.

Paul Fox
Hatayı açan commit: Paul Fox
Paul Fox · 2005-08-01
79c142d93 — new config display applet, from bug 46 — renamed 'config' to 'bbconfig'

Nasıl Düzeltildi

5 Ekim 2006'da Denis Vlasenko (bugünkü BusyBox maintainer'ı, o zamanki kullanıcı adıyla "vda-linux") koca bir "build system overhaul" commit'i attı. Bunun parçası olarak mkconfigs.c tamamen kaldırılıp yerine scripts/mkconfigs adlı bir shell script'i kondu. Yeni script her .config satırını kendi ayrı string literal'i olarak üretiyor (sed -e 's/$/\\n"/') — yani "CONFIG_X=y\n" şeklinde, string'in İÇİNDE değil SONUNDA kaçışlı \n ile. Ardışık string literal'leri C'de otomatik birleştiği için (string concatenation) sonuç tamamen geçerli, tek-satırlık string'lerin art arda dizilmesi oluyor.

Basit ama köklü bir çözüm: veriyi tek dev bir string yerine, C'nin zaten desteklediği "yan yana string'ler otomatik birleşir" özelliğinden faydalanarak üretmek.

Denis Vlasenko
Düzelten commit: Denis Vlasenko
@vda-linux · 2006-10-05
7d219aab7 — build system overhaul

Düzeltmenin Diff'i

Aşağıda düzeltme commit'inin gerçek diff'i var — dosya dosya gezinebilirsin.

scripts/mkconfigs+51 -0
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# Copyright (C) 2002 Khalid Aziz <khalid_aziz at hp.com>
+# Copyright (C) 2002 Randy Dunlap <rddunlap at osdl.org>
+# Copyright (C) 2002 Al Stone <ahs3 at fc.hp.com>
+# Copyright (C) 2002 Hewlett-Packard Company
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# Busybox version by Matteo Croce <3297627799 at wind.it>
+#
+# Rules to generate bbconfig.h from .config:
+# - Retain lines that begin with "CONFIG_"
+# - Retain lines that begin with "# CONFIG_"
+# - lines that use double-quotes must \\-escape-quote them
+
+if [ $# -lt 1 ]
+then
+ config=.config
+else config=$1
+fi
+
+echo "#ifndef _BBCONFIGOPTS_H"
+echo "#define _BBCONFIGOPTS_H"
+echo \
+"/*
+ * busybox configuration settings.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * This file is generated automatically by scripts/config/mkconfigs.
+ * Do not edit.
+ *
+ */"
+
+echo "static const char * const bbconfig_config ="
+echo "`sed 's/\"/\\\\\"/g' $config | grep "^#\? \?CONFIG_" | awk '{print "\\"" $0 "\\\\n\\"";}'`"
+echo ";"
+echo "#endif /* _BBCONFIGOPTS_H */"

Etkilenen Commit'lerden Örnekler