ניתוח קוד סטאטי ובדיקות דינאמיות

דניאל לייזרוביץ,Engineering Software Lab ניתוח קוד סטאטי ובדיקות קוד דינאמיות כשיטות בדיקה משולבות ומשלימות להשגת קוד מקור איכותי ויציב, סקירה מקצועית של שיטות ודרכי פעולה מערכות תוכנה מודרניות הינן לרוב בעלות מספר מאפיינים עיקריים: כמות עצומה של שורות קוד, שהייתה נחשבת לדמיונית רק לפני מספר שנים בודדות; שימוש רב בקוד שמקורו מחוץ לארגון, בין אם קוד מסחרי שנקנה מחברה מתמחה ובין אם קוד פתוח; ומספר רב של מפתחים ברמות שונות של ניסיון והכשרה. דומה, כי רוב רובם של מפתחי התוכנה העובדים בפרויקטים מורכבים וגדולים, בדיקה בכלי בשימוש בצורך הכיר לנתח לסרוק, המסוגלים אוטומטים ולגלות שגיאות תכנות במאות אלפי שורות קוד בזמן קצר. כפועל יוצא, אנו מוצאים עצמנו מתלבטים מהו הכלי המתאים לנו ואיזה כלי ישיג את התמורה הטובה יותר יחסית להשקעה הכספית וזמן ההטמעה האם אחד מכלי ניתוח קוד סטאטי- הקלים יחסית להטמעה ותפעול, או שמא עדיף האם כלי בדיקה דינמי, הקשה יותר להטמעה, אך יוכל לחשוף בעיות שונות? כתיבה לתקן להיצמד מספיק ואוליMISRA כגון)Coding Standard ( מסוים ולהפעיל כלי, ה”אוכף”MISRA CPP אוC את התקן על המפתחים? כאשר מדובר בפרויקטים הדורשים רשיון בתחום התעופהDO178B/C לתקנים, כגון האזרחית בארה”ב, הדרישות ברורות ואנורשות(FAA - פועלים בהתאם להנחיות ה ערעור. יכולת ללא) הפדרלית התעופה אם בדרגת הרישיון שלנו נדרשות בדיקותלמשל( מסוימות)Code Coverage( כיסוי , נצטייד בכלי דינאמי מתאיםMC/DC( ללא לבטים, וכך הלאה. עם זאת יש לזכור, הנו,DO178B/C - ל “מרושיין” שקוד ותמיד יהיה, חלק קטן מהקוד בארגון. ברוב המכריע של המקרים, ההתלבטות תהיה מתוך הצורך והרצון המובן מאליו של מחלקת הפיתוח לייצר קוד יציב, נקי לעלות אירגונית מודעות ומתוך ושלם האפסית של תיקון שגיאות תכנות בשלב הפיתוח, לעומת העלות המטפסת בצורה מעריכית של תיקון אותן שגיאות כאשר , לאינטגרציהQA- הקוד יגיע למחלקת ה ובדיקות מערכת או גרוע מכל, ללקוח.

Upload: daniel-liezrowice

Post on 23-Mar-2016

231 views

Category:

Documents


7 download

DESCRIPTION

ניתוח קוד סטאטי ובדיקות קוד דינאמיות כשיטות בדיקה משולבות ומשלימות להשגת קוד מקור איכותי ויציב, סקירה מקצועית של שיטות ודרכי פעולה

TRANSCRIPT

Page 1: ניתוח קוד סטאטי ובדיקות דינאמיות

דניאל לייזרוביץ,Engineering Software Lab

ניתוח קוד סטאטי ובדיקות קוד דינאמיות כשיטות בדיקה משולבות ומשלימות להשגת קוד מקור איכותי

ויציב, סקירה מקצועית של שיטות ודרכי פעולה

מערכות תוכנה מודרניות הינן לרוב בעלות עצומה כמות עיקריים: מאפיינים מספר של שורות קוד, שהייתה נחשבת לדמיונית רב שימוש בודדות; שנים מספר לפני רק בין אם קוד בקוד שמקורו מחוץ לארגון, אם ובין מתמחה מחברה שנקנה מסחרי קוד פתוח; ומספר רב של מפתחים ברמות

שונות של ניסיון והכשרה. התוכנה מפתחי של רובם רוב כי דומה, וגדולים, מורכבים בפרויקטים העובדים בדיקה בכלי בשימוש בצורך הכיר לנתח לסרוק, המסוגלים אוטומטים ולגלות שגיאות תכנות במאות אלפי שורות קוד בזמן קצר. כפועל יוצא, אנו מוצאים לנו עצמנו מתלבטים מהו הכלי המתאים

ואיזה כלי ישיג את התמורה הטובה יותר ההטמעה וזמן הכספית להשקעה יחסית סטאטי קוד ניתוח מכלי אחד האם -הקלים יחסית להטמעה ותפעול, או שמא עדיף האם כלי בדיקה דינמי, הקשה יותר שונות? בעיות לחשוף יוכל אך להטמעה, כתיבה לתקן להיצמד מספיק ואולי MISRA כגון )Coding Standard ( מסוים C או MISRA CPP ולהפעיל כלי, ה”אוכף”

את התקן על המפתחים?כאשר מדובר בפרויקטים הדורשים רשיון לתקנים, כגון DO178B/C בתחום התעופה האזרחית בארה”ב, הדרישות ברורות ואנו FAA)רשות ה- להנחיות בהתאם פועלים ערעור. יכולת ללא הפדרלית( התעופה

אם בדרגת הרישיון שלנו נדרשות בדיקות כיסוי )Code Coverage( מסוימות )למשל מתאים דינאמי בכלי נצטייד , MC/DC(ללא לבטים, וכך הלאה. עם זאת יש לזכור, הנו, DO178B/C ל- “מרושיין” שקוד בארגון. מהקוד קטן חלק יהיה, ותמיד ההתלבטות המקרים, של המכריע ברוב מאליו המובן והרצון הצורך מתוך תהיה יציב, נקי של מחלקת הפיתוח לייצר קוד לעלות אירגונית מודעות ומתוך ושלם בשלב תכנות שגיאות תיקון של האפסית בצורה המטפסת העלות לעומת הפיתוח, כאשר שגיאות אותן תיקון של מעריכית , לאינטגרציה QA-יגיע למחלקת ה הקוד

ובדיקות מערכת או גרוע מכל, ללקוח.

Page 2: ניתוח קוד סטאטי ובדיקות דינאמיות

“כשיש לך רק פטיש כל בעיה נראית כמו בהשלכה, עממי. פתגם אומר מסמר” בדיקת כלי של הקיים בהיצע נמצא פרוייקטי )מסחריים, אוטומטיים קוד אקדמאיים(, פרוייקטים או פתוח קוד ומוגדר מסוים סוג רק לבצע המסוגלים סטאטי; קוד ניתוח למשל, בדיקות, של הגופים וכיוצ”ב. דינאמיות בדיקות ינסו לשכנע, העומדים מאחורי אותו כלי שביכולתם לספק פתרון מוחלט לכל צרכי בלבד. אחת שיטה באמצעות הבדיקות אינו מהכלים אחד שאף נראה, ואולם השגיאות סוגי של להעדרן לערוב מסוגל כאשר גם למצוא מסוגל הוא שאותן

הבדיקה מדווחת כתקינה.פעם, אחר פעם למדים שאנו כפי בדיקות וסוג יותר, מורכבת המציאות אפילו עקבי מענה לתת מסוגל לא אחד לשגיאות תכנות פשוטות. לצורך ההדגמה נבחן קטע קוד פשוט ביותר )שהוכן לצורך

הדגמת הרעיון בלבד(:

1. #define global /* possible values are global, local, checked_global */2. #if defined (checked_global) || defined (global)3. int *foo_ptr=0x0;4. #endif5. void main(void)6. {7. #if defined (local)8. int *foo_ptr=0x0;9. #endif10. #if defined (checked_global)11. if (foo_ptr == 0x0) 12. #endif13. (*foo_ptr)++; 14. }

של ביותר פשטנית בדוגמא מדובר Null Pointer-כ הידועה התכנות שגיאת ניתוח כלי כל לכאורה, .dereferencingקוד סטאטי אמור לאתר שגיאה זו בקלות, foo_ptr* המשתנה אם המצב זה ואכן המאקרו )כאשר הפונקציה בתוך מוגדר

.)local-בשורה 1 מוגדר כ המצב שונה לחלוטין כאשר אותו משתנה מוגדר מחוץ לפונקציה. אומנם במידה ויש NULL )שימו לב לשורה 11 בקוד בדיקת

1 בשורה והמאקרו במידה המתקמפלת מוגדר כ-Checked_global( כלי ניתוח קוד סטאטי יזהו אותו מיד ויתנו תמיד התראה . Possible Null Pointe Dereferencing של

global כ מוגדר )מאקרו הבא במקרה הניתוח כלי של עיקרית למגבלה נגיע ) foo_ptr* והמשתנה במידה הסטאטיים. מוגדר כמשתנה גלובלי, לא תוצג התראה קלאסיים, סטאטי קוד ניתוח בכלי שכן , Program flow analysis המבצעים נמנעת אלו כלים של הפעולה שיטת מבדיקת המשתנה הגלובלי, בנסיון למזער )התראות השווא התראות כמות את אלו בכלים אינהרנטית בעיה הנם שווא בהפחתתן( מושקעים רבים ומאמצים להשתנות יכול foo_ptr* ש מכוון וזאת על ידי כל קוד בכל זמן, וניסיון למפות את foo_ptr* של ערכו לשינוי האפשריות כל בכל מקום בעץ הקוד יביא את אלגוריתם לבעיית במהירות הכלי של החישוב הנתיבים כל את למפות בניסיון העצירה האפשריים )כלומר אין אלגוריתם שמכריע עבור כל תוכנית Q וקלט X האם התוכנית עוצרת כאשר מופעלת על X כאשרX הינו שיכול בקוד האפשריים הנתיבים מספר לשנות את המצביע מחוץ לפונקציה(, תוך

כדי יצירת התראות שווא רבות.

לא היינו רוצים תוכנית הכוללת קוד זה, בה כל מעבר של הקוד על שורה 13 כאשר תקפה הבלתי לכתובת מצביע foo_ptr*

0x0 ותוביל להתרסקות התוכנית.)את המקרה הפשוט הזה היינו יכולים להציף גם Runtime Exception בדיבאגר אשר היה מייצרבמעבר על קוד זאת, אבל ללא הסבר על גורם

הבעיה וללא ציון מראה מקום מדויק(.

המסוגלת אופיינית, בדיקה להדגמת זה, מסוג תקלות לאתר כן דווקא ,Parasoft חברת של בכלי השתמשנו של ושלם מלא סט כולל בהיותו שיחודו מורכבים, ודינמיים סטאטיים כלים הערוכים לתת מענה מספק לרוב דרישות רישוי לדרישות גם כמו הפרויקט, תקני או DO178B/C כגון פורמליות

.MISRA C/C++ כתיבת קוד כגון)בניגוד דינאמית שבדיקה לראות ניתן את המריצה סטאטית(, קוד לאנליזת Null-ה שגיאת את תזהה בפועל, הקוד foo_ptr* גם אם Pointer Dereferencing

מוגדר כמשתנה גלובלי. Null שגיאת אותה אם יקרה מה אך בתוך נמצאת Pointer Dereferencingהרצה ושום כרגע מתממש שלא ifתנאישנבצע בשלב זה לא תגרום לנו להגיע לצד

?else-השני של ה

תמונה 1.

Page 3: ניתוח קוד סטאטי ובדיקות דינאמיות

כלים, סט שאותו נוח יהיה כזה במקרה ולבדיקות סטאטי קוד לניתוח ששימש גם יכלול בתוכו באופן מובנה דינאמיות, כלי .)Code Coverage ( כיסוי בדיקות כיסוי בדיקות כוללים אכן Parasoft

תמונה 2.

תמונה 3.

קוד וניתוח דינמיות לבדיקות בנוסף סטאטי.

מסוים שינוי מחייבות אלה בדיקות )Tags( “סמנים” הכנסת התוכנית, של הריצה. מסלול אחרי לעקוב כדי לקוד

את להכניס מאפשרים Parasoft כלי של ברזולוציה אוטומטית ה”סמנים” באופן קובץ, חלקי אפילו או בודד קובץ על ה”סמנים” השפעת את שמקטין למינימום התוכנית ריצת ואופי מהירות זמן ביישומי אלא בפועל מורגש שאיננו )Latency( אמת קיצונים בעלי זמני אחזור

קצרים ביותר.הכיסוי בדיקת שכלי נראה 2 בתמונה התנאי ששורת באדום ומסמנים מזהים את ולקדם לגשת כרגע מאפשרת לא *foo_ptr. יתכן שלא קיימת בעיה במקום לדעת לנו מאפשר הסימון אבל זה, שבפנינו קטע קוד שלא רץ ולא נבדק, כך שעשויות להסתתר בו בעיות. שינוי התנאי או סקירה ידנית קפדנית של קטע קוד זה .Null Pointer Dereferencing תסייע לזהות

נשנה הכלים, של נוספת תכונה להדגמת )while)i>0 ובמקום הלולאה תנאי את while הקלאסית השגיאה את נכתוב הנו הלולאה אינדקס כאשר ,))i>=0קוד ניתוח כלי .unsigned int מטיפוס ויראה אינסופית לולאה יזהה סטאטי

שגיאה מתאימה כפי שרואים בתמונה 3:אך למה לפנינו לולאה אינסופית?

תספק הכלי של נוספת בתכונה שימוש מדוע להיזכר שנצטרך מבלי הסבר לנו לאחר ששכח, )למי כך. לכתוב תקין לא ממשיך הקוד ל-0, מגיע שהאינדקס לנסות ולהפחית אותו, מה שנותן למשתנה מסוג טיפוס של המקסימלי הערך את

Unsigned, ומשם חוזר חלילה(. הכתיבה תקן אכיפת מודל את נפעיל Coding Standards enforcement x(הקלאסי הכתיבה בתקן ונשתמש )בתקני שמקורו ,MISRA C והמקובל משמש כיום אך הרכב לתעשיית תוכנה איכותי. בקוד צורך בו שיש מקום בכל טקסטואלית, הנה הבדיקה זה במודל

סמנטית ותלוית הקשר.התקן של MISRA2004-10_1_h-3 סעיף signed בין משתנה מטיפוס אוסר המרה

כפי שקרה unsigned למשתנה מטיפוס

Avoid השגיאה מהודעת כעולה כאן,

implicit conversions between signedand unsigned integer types אותה מראה תקן של ההפרות יתר בין Parasoft-ה

הכתיבה המופיעות בתמונה 4.

הפעלנו 4 סוגי בדיקות שונות: ניתוח קוד

סטאטי, בדיקות דינאמיות, בדיקות כיסוי

Page 4: ניתוח קוד סטאטי ובדיקות דינאמיות

תמונה 4.

תמונה 5.

Parasoft-ה )כלי כתיבה תקני ובדיקות

Unit Testing יחידה בדיקות גם כולל

אבל עקב פשטנות קוד ספציפי זה נמנענו

ואיתרנו אלו( בדיקות סוג מהפעלת

שגיאות תכנות שונות בתנאים שונים.

אבל האם קיימת אפשרות להוכיח באופן

עד נתון? בקוד שגיאות העדר מוחלט

היתה זו לשאלה התשובה לאחרונה

איתור אפשרו קוד בדיקת כלי שלילית.

סיפקו לא אך רבות, תכנות שגיאות

הדבר כאלו. שגיאות שאין הוכחה,

האנליזה כלי של העבודה מאופי נובע

)נקודת מלמעלה העובדים המקובלים

)(main למשל התוכנית של הכניסה

של הקריאות עץ במורד דרכם ועושים

התוכנית, עד נקודת היציאה. ,INFER כלי ניתוח קוד סטאטי חדשני בשםפועל ,MONOIDICS חברת ידי על המיוצר בדרך הפוכה, ומתחיל את הבדיקות מנקודת עד בתוכנית, פרוצדורה כל של היציאה נקודת הכניסה הראשית של התוכנית. כלי להעדר מתמטית הוכחה לספק מסוגל זה מראש מוגדר תכנות שגיאות סוגי מספר המחשב במדעי הידועה הדרך באמצעות

.Separation logic בשם

למה הכוונה?ניצור שוב דוגמת קוד פשוטה:

#include <stdlib.h>

typedef struct node { struct node* tl;} T;

void free_list(T *h) { T *tmp; while (h!=NULL) { tmp = h; h=h->tl; free(tmp); }}

ניהול מבחינת בטוח זה קוד האם

הזיכרון? כלומר, האם ניתן לומר בוודאות

לזיכרון הקשורות שגיאות כאן שאין

Null Pointer וכמובן זיכרון דליפות כגון

?Dereferencingכשהוא בטוח קוד זהו חיובית. התשובה

הפרוצדורה היינו, הנכונה, בדרך מופעל

שיצביע h לפרמטר מצפה free_listלרשימה מקושרת בלתי מעגלית. אם נריץ

h מצביע לרשימה את הפרוצדורה כאשר

כל ללא תשוחרר הרשימה כזו, מקושרת

אם זאת, לעומת זיכרון. ודליפות בעיות

לרשימה מצביע h כאשר הקוד את נריץ

תתרסק התוכנית - מעגלית מקושרת

הראשון האיבר את לשחרר בנסיון

שגיאת יצירת תוך פעמיים ברשימה

. Double Free התכנות הידועה בשם

בעיות של העדרן את הן להוכיח ניתן

Page 5: ניתוח קוד סטאטי ובדיקות דינאמיות

שבסיום והן לזיכרון הקשורות

הרשימה של האלמנטים כל הפרוצדורה

שוחררו, וזאת בהרצה על גבי רשימה לא-

מעגלית.

כאילו זו פעולה לתאר ניתן בהשאלה

אפשרויות כל את מנסה INFER ה- כלי

ההתנהגות בזמן ריצה )בניגוד לכלי ניתוח

למספר המוגבלים רגילים, סטאטי קוד

נתון של אפשרויות ריצה(.

לצורך האנלוגיה ניקח את משפט פיתגורס

זווית ישר בעל משולש “בכל האומר

שווה היתר על המונח ריבוע של השטח

על המונחים ריבועים שני של לסכומם

הניצבים.

אם נרצה להוכיח את המשפט נוכל לקחת

את ונבדוק משולשים של כלשהו מספר

שנקבל להניח סביר אמפירית. הטענה

את הוכחנו לא בכך אבל נכונה, תוצאה

פרטיים מקרים מספר אלא המשפט,

בלבד.

הפשטה על נתבסס אם זאת, לעומת

מתמטית וסט של אקסיומות, ניתן להוכיח

המשולשים לכל תקף פיתגורס שמשפט

ישרי הזווית.

הקוד ניתוח כלי שאר דוגמא, אותה לפי

מקרים של הוכחה מספקים הסטאטי

תשובה מספק שאינו באופן פרטיים

בעוד משמעית, וחד מוכחת מבוססת,

מייצרת INFER של העבודה ששיטת

מסנתזת המקרים, לכל שטובה הוכחה

את תנאי היסוד )המקבילה לאקסיומות(

לכל בונה את הוכחה, התקפה גביהן ועל

התנאים.

הינו היסוד תנאי שלמעלה בדוגמא

ניתן ואז מעגלית, לא ברשימה שמדובר

להוכיח באופן אוטומטי שבאף מקרה של

. Double Free לא יתבצע שחרור כפול

טיפוסי הוכחה מבנה נראה 5 בתמונה

שמוצגת כפי שגיאות( של )להעדרן

למשתמש ועבור פרוצדורה בשם

int copy_siginfo_to_user32)compat_

)siginfo_t __user *to, siginfo_t *from

המקור קוד מתוך הנה זאת פרוצדורה

linux/ של קרנל הלינוקס גרסה 2.6 )קובץ

שהנו arch/x86_64/ia32/ia32_signal.c

ידי על אחד הקבצים המקוריים שנכתבו

לינוס טרוולדוס ב 1992 (.

מפתחי לרשות עומד לראשונה לסיכום,

התוכנה כלי, המסוגל לא רק לאתר שגיאות

מדובר להעדרן. הוכחה לספק גם אלא

בכלי שימושי ביותר ביישומים קריטיים,

ואין פלא שהשימוש בו אומץ לבדיקת קוד

בבקרת AirBus כגון תעופה בפרוייקטי

מערכות רכבות, כורים אטומים ויישומים

קריטיים דומים אחרים.

הסקירה נכתבה עלי ידי דניאל לייזרוביץ מחברת בשרותי המתמחה תוכנה מערכות אי.אס.אל. ביצוע, פיתוח הטמעה וכלים לניתוח קוד סטאטי הערות נוספות בשאלות דינאמיות, ובדיקות

ובקשות מידע ניתן לפנות [email protected]