ב-Online
 
 
 
 
 
 
 
לפרק את הבייט 
בהנחה שהקלט תקין 
 
לפרק את הבייט |
 

וידוא תקינות הקלט הוא אחת המשימות המפרכות והמשעממות ביותר עבור מתכנתים - אך הוא בעל חשיבות עליונה. עידו גנדל יכיר לכם את מערכת הביוב של התוכנה

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

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

נח בשבע שגיאות

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

נניח שאנו מבקשים מהמשתמש להקליד מספר. לכאורה, הבדיקה היחידה שצריך לעשות היא לוודא שלא הוקלדו פנימה בטעות אותיות או תווים מיוחדים – רק ספרות. אבל כמובן, ייתכן גם מספר שלילי או מספר עם נקודה עשרונית. במקרה כזה צריך להיזהר: לא סתם לאפשר לשני התווים האלה להופיע, אלא רק במקומות בהם יש להם משמעות. בנוסף, ברוב שפות התכנות יש מגבלה ברורה לגודל המספר שמשתנה יכול להכיל. משתנה מסוג Integer הנפוץ בגודל 32 ביט (הכולל סימן) יכול להגיע עד 2,147,483,647. מה עושים אם המשתמש מקליד מספר גדול יותר? ומה לגבי משתמש שמקליד עם פסיקים להפרדה בין אלפים, כמו שעשינו כאן, או בסימון מדעי ("1.2E06")?

כל אלה הן בעיות טכניות. גם אם התגברנו על כולן (וכל שפות התכנות כוללות כלים שיעזרו לנו בזה), עדיין צריך לחשוב מה המשמעות של המספר הזה בתוכנה. אם הוא מייצג את שנת הלידה של אדם, הוא אינו יכול להיות גבוה יותר מהשנה הנוכחית. אם מדובר על הגובה של אדם בוגר בסנטימטרים, הערך החוקי ינוע בין 57 ל-272 – אם כי בהתחשב בהתפלגות הגובה באוכלוסיה, כדאי מאד לבקש מהמשתמש לבדוק את עצמו שוב בערכים קיצוניים.
 
השגיאות תלויות גם בשימוש של הקלט בתוכנה
 השגיאות תלויות גם בשימוש של הקלט בתוכנה   צילום: flickr, slashcrisis, cc by sa  
 
 

לצמצם את חופש הבחירה

כל הדוגמאות לעיל מניחות שהמספר מוקלד לתוך תיבת טקסט סטנדרטית, נקלט מקובץ טקסט או מתקבל כטקסט חופשי ב-Command prompt כלשהו. עם זאת, רוב ממשקי הקלט שתתקלו בהם כיום הם ממשקים גרפיים, שעושים שימוש ברכיבי קלט תקניים שמצמצמים את האפשרות לטעות. כאשר הקלט בינארי (כן/לא, גבר/אישה וכו') נהוג להשתמש בתיבת סימון או ב"לחצני רדיו" שמגבילים את המשתמש אך ורק לאפשרויות שהמתכנת הגדיר. כאשר יש מספר גדול יותר של ערכים אפשריים, או כשרוצים לחסוך במקום, אפשר לעבור ל-ComboBox – ה"תיבה הנפתחת" המפורסמת, אותה אפשר להגביל כך שלא תקבל ערכים בהקלדה חופשית. אפילו ערך מורכב יחסית כמו תאריך אפשר לקלוט בלי שהמשתמש יקליד אפילו תו אחד – רק בעזרת הקלקות עכבר על רכיב "לוח שנה" מתאים.
 
אין מקום לטעויות (צילומסך: עידו גנדל)
 אין מקום לטעויות (צילומסך: עידו גנדל) 
 
גם אם הקלט מורכב מכדי להגדיר את כל האפשרויות מראש, עדיין אפשר לחלק אותו לחלקים קבועים וחופשיים ולצמצם את הסיכוי לטעות. למשל, כאשר מזינים את מספר הטלפון לתוכנה או לאתר שמיועדים לשוק הישראלי, המשתמש מקבל לרוב ComboBox עם אזורי החיוג האפשריים, ותיבת טקסט נפרדת למספר עצמו. כך לפחות נמנעות השגיאות הפוטנציאליות בהקלדת אזור החיוג ומתקבל פורמט אחיד לכל המספרים. בקיצור, השלב הראשון בסניטציה של קלט הוא למזער למינימום את הגמישות שאנו נותנים למשתמש בהזנת הערכים.
 

עקרון הזבל

קורה שמזינים נתון חוקי לשדה שגוי
 קורה שמזינים נתון חוקי לשדה שגוי 
 צילום: flickr, mwin, cc by sa 
 
בעולם המחשבים קיים חוק מפורסם: Garbage In Garbage Out, כלומר אם התוכנה מקבלת קלט שהוא זבל, גם התוצאה תהיה זבל ולא משנה עד כמה התוכנה עצמה משוכללת וחכמה. אפשר ללמד מחשב-על לבצע חישובי מסלולים לחלליות ברמת דיוק מטורפת, אבל אם אומרים לו בטעות שהמרחק לירח הוא 380,000 מטרים במקום קילומטרים, כל הדיוק שבתוכנה לא יעזור – התוצאה תיכשל במבחן המציאות: המחשב ביצע חישוב נכון, אבל על נתונים שגויים.

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

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

סכנה ברורה ומיידית

קלט שגוי יגרום ברוב המקרים לתוצאות אבסורדיות או לקריסה של התוכנה, אך הוא עלול גם לגרום לאסונות. שגיאה שלא תיתפס בזמן במערכות מחשב רפואיות, למשל, או במערכות צבאיות, תעלה בחיי אדם. האם אתם יכולים לדמיין לעצמכם תוכנה שמנהלת כור גרעיני או מערך טילים בליסטיים, ושהמתכנת שלה הלך לפי הכלל המוכר "הנח שהקלט תקין"? קלט לא הגיוני שלא נתפס בזמן כבר עלה לבנק יפני 340 מיליוני דולרים בסוף שנת 2005, כאשר סוחר בבורסה מכר 610,000 מניות תמורת ין אחד לכל מניה, במקום להיפך – תמורת 610,000 ין למניה אחת.
 
צילום: flickr, Joshua Davis (jdavis.info), cc by sa
 צילום: flickr, Joshua Davis (jdavis.info), cc by sa    
סכנה נוספת למערכות מחשב נוצרת כאשר נעשה בקלט שימוש ישיר בתוך קוד תוכנה. נתחיל בדוגמה פשוטה: בשפת התכנות C, הפונקציה הוותיקה printf לכתיבה על המסך מתייחסת למחרוזת "n\" בתור הוראה לקפוץ לשורה הבאה. נניח שכתבנו ספר טלפונים בשפת C, עם אפשרות להציג את כל הרשומות בטבלה מסודרת על המסך, ונניח שמשתמש זדוני כלשהו הזין לתוכנה את השם "משה כהןn\". אם לא נבצע סינון של הקלט, המחרוזת הזו תגיע לפקודת ה-printf והטבלה היפה שלנו תישבר מיד לאחר השם "משה כהן".

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

הוסף 'X' לטבלה Y

X עדיין אינו מוגדר – זהו הערך שהמשתמש יזין. כאשר מתקבל הערך ("משה כהן"), התוכנה מחליפה את X שבתבנית בקלט ואז מריצה את הפקודה כולה, באופן הבא:

הוסף 'משה כהן' לטבלה Y

שימו לב לגרשים שמסביב לשם – הם מהווים חלק מהתבנית ומודיעים למפענח ה-SQL שמדובר בטקסט ולא בפקודה. אבל מה יקרה אם במקום "משה כהן", ההאקר שלנו יכתוב בשדה "שם" את המחרוזת הארוכה "משה כהן' לטבלה Y, מחק את כל הטבלאות, הוסף 'נדפקתם"?

הוסף 'משה כהן' לטבלה Y, מחק את כל הטבלאות, הוסף 'נדפקתם' לטבלה Y

לסיכום, כאשר אתם כותבים תוכנה עבור העולם האמיתי, לעולם אל תניחו שהקלט תקין.

לטורים נוספים במסגרת לפרק את הבייט
 
 
 
@@@@@@@@@@@@@@@@@@@ ilan @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
@@@@@@@@@@@@@@@@@@@ ilan @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 
תגובות
הוסף תגובה0 תגובות
הוספת תגובה
מאת
 
נושא
 
תוכן
 
 
 
 
תודה! תגובתך התקבלה.
התגובה תתפרסם בכפוף לתנאי האתר.
 
 
 
 
 

כל הזכויות שמורות 2011 © נענע 10 בע"מ
 
 
 
 
כל הזכויות שמורות © Nana10 בע"מ
Video powered by