IRCAR201106104
تاريخ: 21/03/90
عنصر اصلي در برنامهنويسي امن با زبانهاي مختلف برنامهنويسي، مستندسازي خوب و استفاده از استانداردهاي قابل اجرا است. استانداردهاي كدنويسي، برنامهنويسان را ترغيب به پيروي از مجموعهاي متحدالشكل از قوانين و راهنماييهايي ميكند كه بر اساس نيازمنديهاي پروژه و سازمان تعيين شده است، نه بر اساس سلايق و مهارتهاي مختلف برنامهنويسان. به محض تعيين استانداردهاي مذكور، ميتوان از آن به عنوان معياري براي ارزيابي كدهاي منبع، چه به صورت دستي و چه به صورت اتوماتيك استفاده كرد.
از استانداردهاي معروف در اين زمينه ميتوان به استانداردCERT براي كدنويسي امن اشاره كرد كه يك سري از قوانين و پيشنهادات را براي كدنويسي امن با زبانهاي برنامهنويسي C، C++ و جاوا ارائه ميدهد. هدف از اين قوانين و پيشنهادات، حذف عادتهاي كدنويسي ناامن و رفتارهاي تعريف نشده است كه منجر به آسيبپذيريهاي قابل سوءاستفاده ميشود. به كارگيري استانداردهاي مذكور منجر به توليد سيستمهاي با كيفيت بالاتر ميشود كه در برابر حملات بالقوه، پايدارتر و مقاومتر هستند.
در مقالههاي قبلي، كليات استاندارد CERT در زمينه مزبور را توضيح داديم و در سري مقالههاي برنامهنويسي امن به زبان C به صورت تخصصيتر شيوه برنامهنويسي امن با اين زبان را مورد بررسي قرار ميدهيم. قابل ذكر است كه در اين استاندارد 89 قانون و 134 پيشنهاد براي برنامهنويسي امن با زبان C ارائه شده است كه در اين سري مقالات، مهمترين آنها را كه در سطح يك قرار دارند، شرح خواهيم داد. براي كسب اطلاعات بيشتر در مورد سطحبندي قوانين و پيشنهادات به مقاله "آشنايي با استاندارد CERT براي برنامه نويسي امن" مراجعه فرماييد. سري مقالات حاضر با عنوان قوانين و پيشنهادات تكميلي (Miscellaneous) آخرين سري مقالات برنامهنويسي امن به زبان C است كه در آن قوانين و پيشنهاداتي توضيح داده ميشوند كه در دسته بنديهاي قبلي نگنجيدهاند.
43. MSC17-C – هر مجموعه دستوراتي را كه با case شروع ميشود با دستور break تمام كنيد.
دستور switch شامل قسمتهاي مختلفي با برچسب case به علاوه يك برچسب default است. البته قسمت default اختياري بوده ولي استفاده از آن توصيه شده است. مجموعه اي از دستورات كه در ادامه برچسب case ميآيند، نهايتاً با يك دستور break خاتمه مييابند. در صورتي كه اين دستور حذف شود، كنترل برنامه به case بعدي ميرود. از آنجايي كه دستور break مورد نياز نيست، حذف آن يك خطاي كامپايلر را توليد نميكند. در وضعيتي كه حذف break به صورت غيرعمدي اتفاق بيفتد، ميتواند منجر به رفتار تعريف نشده شود.
در زير برنامهاي را ميبينيد كه در آن استفاده از دستور break در حالتي كه widget_type مقدار we_w داشته باشد، فراموش شده است. در نتيجه دستوراتي كه بايد تنها در صورتي كه widget_type براير با we_x باشد اجرا شوند، در حالتي كه widget_type برابر با we_w باشد نيز اجرا ميشوند.
enum WidgetEnum { WE_W, WE_X, WE_Y, WE_Z } widget_type; widget_type = WE_X; switch (widget_type) { case WE_W: /* ... */ case WE_X: /* ... */ break; case WE_Y: case WE_Z: /* ... */ break; default: /* can't happen */ /* handle error condition */ }
در برنامه اصلاحشده زير هر ترتيبي از case ها داراي دستور break معادل هستند:
enum WidgetEnum { WE_W, WE_X, WE_Y, WE_Z } widget_type; widget_type = WE_X; switch (widget_type) { case WE_W: /* ... */ break; case WE_X: /* ... */ break; case WE_Y: case WE_Z: /* ... */ break; default: /* can't happen */ /* handle error condition */ }
بعد از we_y نيازي به دستور break نيست زيرا هيچ دستوري در آن وجود ندارد و نشان دهنده اينست كه در صورت بروز we_y و we_z نيازمند يك نوع از رفتار هستيم.
همچنين دستور break در قسمت default مورد نياز نيست، چرا كه اين حالت بر روي جريان كنترل برنامه تأثيري ندارد.
استثناءها:
- MSC17-EX1: آخرين برچسب در دستور switch نيازمند يك braek در پايان نيست زيرا اين برچسب در نهايت همان برچسب پيشفرض است.
- MSC17-EX2: زماني كه نياز است كه جريان كنترل در چندين case بيفتد، مجوز حذف كردن دستور break وجود دارد، اما در اين نمونهها، حتماً بايد اين جريان كنترل غيرعادي به صورت روشن در مستندات آورده شود.
enum WidgetEnum { WE_W, WE_X, WE_Y, WE_Z } widget_type; widget_type = WE_X; switch (widget_type) { case WE_W: /* ... */ /* no break, process case for WE_X as well */ case WE_X: /* ... */ break; case WE_Y: case WE_Z: /* ... */ break; default: /* can't happen */ /* handle error condition */ }
در پايان يادآوري مي شود كه استفاده نكردن از دستور break در دستور switch و در پايان هر برچسب case منجر به جريان كنترل غير منتظره ميشود.
- 5