غير فارغ من إنهاء السلسلة - خطأ Klocwork دون سبب مفهوم

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

  •  02-10-2019
  •  | 
  •  

سؤال

لقد قمت مؤخرًا بتثبيت "Klocwork" وأحاول التخلص من الأخطاء على رمز موجود. يبدو أن الخطأ الموضح بسيط. لا خالية في إنهاء char * _p_. لقد أضفت يدويًا إنهاء فارغ (على الرغم من عدم وجود حاجة) ، لكن هذا لا يرضي العمل. أيه أفكار؟

الرسالة الدقيقة هي:-

سلسلة إنهاء بشكل غير صحيح 'صيسبب تدفق مخزن مؤقت في ص.

char *ptr;
int writtenchars = 0 ;
va_list args;  
char* destStr;

if (argc != 2) {
  printf(" wrong parameters number - %d instead of %d\n", argc, 2);
  char  str[25]="wrong parameters number ";
  char *_p_; /********************************************************/

  va_start(args, str);
  destStr = (char*) malloc(SNMP_BUF_LEN);
  _p_= destStr;
  if (destStr == NULL) {
    printf("WARNING: Failed to alloc memory in in function \"snmp_rebuildstringinbuf!!!\" \n");
    destStr="kukuRiko";
  }
  else {
    writtenchars = (int) vsnprintf(destStr, 4095, str, args);
    if (writtenchars>SNMP_BUF_LEN) {
      printf("WARNING: Too long string rebuilded in function \"snmp_rebuildstringinbuf!!!\" %d chars\n",writtenchars);
    }
    destStr[writtenchars] = '\0' ; //Moshe - making sure the last value of the string is null terminated in order to prevent future buffer overflows.
  }
  va_end(args);

  /******************************************************************************/
  //The KlocWork error relates to this line //

  logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue); 
  free (_p_);   

================================================== ========== مرحبًا يا شباب ، شكرًا على إجاباتك ، لكن يبدو الأمر أكثر غموضًا من ذلك. لقد قمت بتحسين الرمز إلى هذه الحالة البسيطة:- عندما يتم كتابة الرمز كله في وظيفة واحدة ، لا يوجد خطأ ، بينما ، عندما يتم لف قسم التخصيص في وظيفة (ويتم تمرير نص كمعلمة) ، يعود خطأ Klocwork. انظر هذا الرمز:- الإصدار بدون خطأ:-

char *_p_; /*+++++++++++++++++++*/

 int writtenchars = 0 ;
 va_list args;  
 char* destStr;
 char* str = "hello World"; 
 va_start(args, str);
 destStr = (char*)malloc(SNMP_BUF_LEN);
 if (destStr == NULL) {
   printf("WARNING: Failed to alloc memory in function \n");
 }
 else {
   writtenchars = (int) vsnprintf(destStr, (SNMP_BUF_LEN) - 1, str, args);
 }

 /*+++++++++++++++++++*/
 _p_ = destStr ;
 if (_p_ != NULL) {
   logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue); 
 }
 free (_p_);
 /***********************************************************/

بينما عند أخذ الكود بين / *++++ * / ولفه في دالة ، يقوم بإرجاع خطأ Klocwork أعلاه.

بالتالي،

char *writingToSomeBuffer (char * str) {
  int writtenchars = 0 ;
  va_list args;  
  char* destStr;
  va_start(args, str);
  destStr = (char*)malloc(SNMP_BUF_LEN);
  if (destStr == NULL) {
    printf("WARNING: Failed to alloc memory in function \n");
  }
  else {
    writtenchars = (int) vsnprintf(destStr, (SNMP_BUF_LEN) - 1, str, args);
  }
  return destStr;
}

int main () {
  char *_p_;
  _p_ = writingToSomeBuffer("hello world");
  if (_p_ != NULL) {
    logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue); 
  }
  free (_p_);
  return 0 ; 
}

أيه أفكار؟

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

المحلول

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

http://www.klocwork.com/products/documentation/insight-9.1/checkers:nnts.might http://www.klocwork.com/products/documentation/insight-9.1/checkers:nnts.must

نحن قيد التطوير حاليًا لتنظيف هذا وتسهيل فهمه. ليس فقط المشكلة ولكن الحل كذلك.

نصائح أخرى

يتم تشخيص Klocwork بشكل صحيح المشكلة التي يمكنك الكتابة بها مع مؤشر فارغ إذا فشل تخصيص الذاكرة:

_p_= destStr;
if (destStr == NULL)
{
    printf("WARNING: Failed to alloc memory in in function ...\n");
    destStr = "kukuRiko";

في هذه المرحلة ، (المسماة بشكل فظيع) "_p_"المتغير لا يزال فارغًا ، لكنك تمضي قدمًا وتستخدمه في عملية الطباعة أدناه.

لاحظ أيضًا أن الإصلاح "التافلي" للإضافة "_p_بعد هذا يكسر إدارة الذاكرة ؛ أنت في وقت لاحق تفعلfree(_p_);"مما سيؤدي إلى مشاكل مروعة إذا"_p_يشير إلى السلسلة الثابتة.

لديك أيضا الذاكرة في في وظيفة 'في الرسالة. و "رقم المعلمات الخاطئة" يعني تقريبا نفس "العدد الخاطئ من المعلمات" ولكن الأخير هو أكثر إنجليزية الاصطلاحية. أنا لست مقتنعا بأي من علامات التعجب مفيدة في رسالة الخطأ ؛ هناك حجة قوية مفادها أنهم يجب أن يخرجوا خارج الاقتباسات المزدوجة المحيطة باسم الوظيفة حتى لو كان أحدهم مرغوبًا فيه.


من خلال النسخة المنقحة من المشكلة ، أتساءل عما إذا كان Klocwork يقوم بتشخيص ما تقوله Microsoft vsnprintf (), ، أنه لا يضمن الإنهاء الفارغ (وهو ما يختلف عن ما C99 و Posix يقول).

خطأ Klocwork جانباً ، أعتقد أن هذا الرمز خاطئ. لماذا تحصر vsnprintf إلى 4096 ، في حين أن حجم المخزن المؤقت SNMP_BUF_LEN؟ كيف يرتبط هذان الاثنان ببعضهما البعض؟ إذا SNMP_BUF_LEN <4096 ، ثم قد تفيض للتو المخزن المؤقت الخاص بك. لماذا لا تمر SNMP_BUF_LEN كحجة محددة في VSNPRINTF؟

أيضا ، الكتابة إلى destStr[writtenchars] مشتبه به. اعتمادًا على متغير VSNPRINTF (يختلفون) ، قد يكون المكتوب عدد الأحرف مطلوب للكتابة ، مما سيجعلك مرة أخرى تكتب نهاية المخزن المؤقت الخاص بك.

هذا كل ما قيل ، Klocwork ليس مثاليًا. كان لدينا وحدات ماكرو التي كانت تحاول صراحةً أن تكون آمنة ، وقد أسيء اكتشافها على أنها قد تجاوزت السلسلة. أعتقد أن هذه كانت حالة snprintf كذلك.

بشكل عام ، يكون منتجًا جيدًا ، ولكن يحتوي على عدد قليل من الثقوب ولا يمكنك إصلاح كل الشكاوى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top