آمن C والجامعات - مدربين لتجاوز سعة المخزن المؤقت

StackOverflow https://stackoverflow.com/questions/483018

  •  20-08-2019
  •  | 
  •  

سؤال

وانتهيت مؤخرا دورة الجامعة في C. لذلك أنا يفتقرون إلى الخبرة، بطبيعة الحال.

وبعض الجامعات تميل لتعليم طلابهم برمجة آمنة، <وأ href = "http://www.courses.fas.harvard.edu/~cs50/get/podcasts/2007/lectures/notes9m.pdf" يختلط = " نوفولو noreferrer "> أو على الأقل بعض العناصر . هناك حتى فيديو ( مأخوذة من هنا ).

ويجري في C، سلاسل نسخ، يتطلب - بقدر ما أعرف - وظائف strcpy أو string.h. كيف يمكنك استخدامها بشكل آمن في كل يوم البرمجة؟ هل لديك بعض الوظائف، التي تتعامل مع تخصيص لمنع عازلة الفيضانات؟ هناك هو CERT آمن مستوى الترميز لC . انها تقدم أمثلة والحلول المتوافقة:

int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[128];
  strcpy(prog_name, argv[0]);
  /* ... */
}

والبديل لها هو:

int main(int argc, char *argv[]) {
  /* ... */
  char *prog_name = (char *)malloc(strlen(argv[0])+1);
  if (prog_name != NULL) {
    strcpy(prog_name, argv[0]);
  }
  else {
    /* Couldn't get the memory - recover */
  }
  /* ... */
}

والمحصلة من هنا، <وأ href = "https://www.securecoding.cert.org/confluence/display/seccode/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space + للطابع + + بيانات + و + ل+ اغية + فاصل "يختلط =" نوفولو noreferrer "> مثال 2 .

ولكن بقدر ما أحصل عليه هذا هو أكثر تحديا فقط، رمز أكثر، المزيد من العمل. لماذا لا أحد تغيير المكتبة نفسها؟ أو على الأقل لماذا لا أحد توفر مكتبة بديل آمن أو وظائف، والذي تعامل مع هذا بالطريقة الصحيحة؟

وشكرا للقراءة، wishi

هل كانت مفيدة؟

المحلول

وظيفة POSIX لهذا (متوفر على تقريبا كل نظام) هي strdup(). يستخدم strcpy() إذا كنت لا ترغب في تخصيص ذاكرة جديدة وبالفعل لدينا منطقة عازلة التي تريد استخدامها، ولكن بعد ذلك والمعروف كيف كبيرة أن المخزن المؤقت وإذا كانت السلسلة يناسب في ذلك. إذا كنت لا تعرف إذا كانت السلسلة تناسبها، هناك strncpy() أن مجرد نسخ عدد معين من الأحرف. حتى تتمكن من الحد من كمية نسخها إلى حجم المخازن الخاصة بك.

وبالإضافة إلى ذلك، هناك الكثير من المكتبات اللدغة التي تدير أحجام سلسلة بطرق مختلفة.

ومنذ كنت الموسومة ذلك ج ++: هناك std::string أن يفعل كل إدارة الذاكرة لديك ولا تعطيك هذه المشاكل

نصائح أخرى

وعلى ل (strlcpy، strlcat) وظائف من اكبر برهان عادة ما تكون أفضل من ن وظائف، وكلاهما أسرع وأسهل للاستخدام آمن، لكنها غير قياسي. ومع ذلك، يتم BSD الترخيص لها حتى تتمكن تشمل تنفيذ جيدة معروفة في أي برنامج حتى تتمكن يمكن أن تكون عبر منصة وآمنة.

لWindows، إذا كنت لا تهتم حول قابلية، يمكنك استخدام * وظائف _s.

استخدم strncpy :

#define BUFSIZE 127
int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[BUFSIZE + 1];
  strncpy(prog_name, argv[0], BUFSIZE);
  progname[BUFSIZE]= '\0';
  /* ... */
}

وهناك إصدارات *n* لمعظم وظائف str*.

إذا فهمت بشكل صحيح، والسؤال الحقيقي هو لماذا لم تتم وظائف API أكثر أمنا.

وأحد الأسباب السبب هو أن C المكتبة القديمة (بعد فوات الأوان لتغييره الآن).

والسبب الرئيسي، ومع ذلك، هو أن المكتبة تم تصميمه ليكون في أضيق الحدود، بحيث لا الحد الأدنى، وأنه تقع على عاتق المستخدم للتأكد من أن يتم استدعاؤه بشكل صحيح. إذا كان القيام بأي الشيكات المفرطة، ثم الثمن الذي يجب أن يدفع كل مرة يطلق عليه، حتى لو كان يمكن للمستخدم ضمان لأسباب أخرى أنه لا توجد مشكلة سوف تحدث. هذا هو جدا شائع جدا في العديد من واجهات برمجة التطبيقات.

وأن يقال، وهناك ما يكفي من المكتبات التي توفر بدائل أكثر أمانا، وانهم فقط ليس جزءا من المكتبة القياسية. أيضا، فإن العديد من الناس الذين لا أعلى مستوى العمل الاشياء مع C ++، التي لديها مكتبات فئة القياسية للعديد من تلك الأشياء.

والواقع، ومايكروسوفت لم تقدم بدائل آمنة إلى وظائف CRT. الجميع وأنا أعلم يكره لهم على الرغم من وتعطيل التحذير التي يجب أن لا تستخدم وظائف القديمة. إذا كنت تريد شيئا آمن، ربما يجب عليك استخدام C ++. وبعد ذلك إما STL سلاسل أو شيء من هذا القبيل كيو تي.

حسنا، أو تذهب إلى منصات مثل .NET أو جافا، والتي عادة لا يعانون من هذه المشاكل (التطبيق الخاص بك قد تحطم، ولكن توجد طريقة لحقن البرمجية في التطبيق الخاص بك من خلال تجاوز سعة المخزن المؤقت).

وتحرير: مع منع تنفيذ البيانات / NX تمكين (الافتراضي لفيستا و. NET)، وهذا لا ينبغي أن يكون مشكلة لمنصات التقليدية أيضا.

int main
(
    int argc, 
    char *argV[]
) 
{
   char prog_name[128];
   if (strlen(argV[0]) < sizeof(prog_name))
   {
       strcpy(prog_name, argV[0]);
   }
   else
   {
       printf("%s is too large for the internal buffer\n", argV[0]);
   }

   return 0;
}

وربما سوف تجد إجابات القراءة مفيدة ل هذا السؤال

scroll top