אגב, אני מבסוט על אלון(DLN) שהבין את הבדיחה הסופר-דופר-שנונה בכותרת של ההודעה(בסימן קצת אחר...)
אח, רואים שהוא ***ניק 3> ולעניין:
כמו שאלון כתב, אנחנו נפלנו על קטע של signed/unsigned mismatch.
הפונקציה שכתבתי מקבלת את האורך המחרוזת כ int. כלומר, אורך המחרוזת
שלי יכול להיות מיוצג גם כמספר שלילי וגם כמספר חיובי.
אם נסתכל על הprototype של memcpy, נראה את הדבר הבא:
void * memcpy ( void * destination, const void * source, size_t num );
|
ומה הוא הטיפוס size_t?
typedef unsigned long size_t;
|
(ספציפית, אגב, זה תלוי קומפיילר - יכול להיות שאצלכם בקומפיילר זה יוגדר כ- unsigned int).
מה שחשוב הוא לשים לב שsize_t הוא תמיד unsigned! כלומר, אין לו סימן.
מה יקרה אם ננסה לעשות cast מ- int שלילי ל unsigned int? לדוגמה, אם
נעשה cast מ int שמכיל -1, לunsigned - נקבל 4294967295.
מבינים את ההגיון? הוא לא יודע להתמודד עם מספרים שלילים - אז הוא פשוט מתחיל לספור שוב מה"סוף" של הסקאלה.
ואחרי החפירה - מה זה אומר?
זה אומר, שאם אני אתן כ len לדוגמה, -1, תהיה לי גישה לbuffer עצום בזכרון שלכם.
מה זה אומר בתכלס? שאם את הנתון הזה הייתם מקבלים לדוגמה מהאינטרנט דרך סוקט,
הייתי יכול לעשות buffer overflow קלאסי וכיפי, ולהריץ קוד על המחשב שלכם(ומשם השמיים הם הגבול ).
אני מקווה שאתם רואים כמה קשה לעלות על זה - וזה אחד הבאגים הנפוצים
בעולם. במקרה אמיתי לדוגמה ראיתי מאמר שמישהו פרסם על חולשה שהוא מצא ב ftp server כלשהו, שפשוט עבד בצורה דומה -
הגודל התקבל בבייט הראשון של איזשהו סטרים של מידע, ואכן הגודל נבדק
(ככה שהמתכנת חשב שהוא כתב קוד בטוח, כן בטח ), אבל הוא חטא ב signed/unsigned mismatch.
לסיכום - תשימו לב טוב לדברים האלה. תכתבו קוד בטוח. זה חשוב
תגובות יתקבלו בברכה
לירן.
\x6C\x65\x65\x74\x68\x61\x78\x30
\x72\x3A\x2D\x29
tresp4sser