บัฟเฟอร์โอเวอร์โฟลว์เปลี่ยนชนิดข้อมูลของตัวแปรที่เป็นการเขียนทับหรือไม่? [ปิด]


8

char buf[15]บอกว่าผมมีอาร์เรย์ตัวอักษร C ตัวแปร Say มีข้อมูลที่จัดเก็บไว้ในสถานที่ตั้งของหน่วยความจำโดยตรงหลังจากint set_me = 0 char buf[15]ถ้าฉันล้นbufด้วยเชือก"aaabbbcccdddeee\xef\xbe\xad\xde"ก็จะset_me's เปลี่ยนแปลงชนิดข้อมูลจากจำนวนเต็มอาร์เรย์ตัวละครอยู่แล้ว?


3
ขึ้นอยู่กับว่าใครเป็นผู้ตีความข้อมูล ในที่สุดทุกอย่างเป็นไบนารี ดังนั้นวิธีที่คุณตีความมันอาจเป็นค่าจำนวนเต็มที่ถูกต้องหรือทำให้เกิดข้อผิดพลาดในการโยน
Ganesh R.

คำตอบ:


33

เลขที่

"ชนิดข้อมูล" ของตัวแปรเกี่ยวข้องเฉพาะในซอร์สโค้ด (และในบางภาษาเท่านั้น) มันบอกคอมไพเลอร์วิธีการรักษาตัวแปร

ชนิดข้อมูลระดับสูงเหล่านี้ไม่มีอยู่ในโค้ดที่แปล (เนทีฟ) พวกเขาสามารถส่งผลกระทบต่อสิ่งที่สร้างคอมไพเลอร์ แต่คำแนะนำตัวเองไม่สนใจว่าข้อมูลหมายถึงตัวละครหรือตัวเลข


ตัวแปรไม่มีอยู่ในฮาร์ดแวร์ ในฮาร์ดแวร์คุณมีตำแหน่งหน่วยความจำและคำแนะนำที่ใช้งานได้

ตัวแปรอาจถูกมองว่าเป็นมุมมองของข้อมูลที่ตำแหน่งหน่วยความจำ - ถ้าคุณเหล่และดูที่หน่วยความจำเดียวกันแตกต่างกันเล็กน้อย (ตัวแปรที่แตกต่างกับชนิดที่ต่างกันซึ่งอ้างถึงที่ตั้งเดียวกัน) ค่าไบนารีเดียวกันอาจมีความหมายแตกต่างกัน .

ยกตัวอย่างเช่น 0x41 Aไบต์อาจจะตีความว่าเป็นตัวละคร มันอาจถูกตีความว่าเป็นจำนวนเต็มไบต์65เดียว มันอาจตีความได้ว่าเป็นหนึ่งไบต์ในจำนวนเต็มจำนวนเต็มหรือจำนวนทศนิยมหรือหนึ่งไบต์ในการเข้ารหัสอักขระแบบหลายไบต์ มันอาจเป็นบิตเซ็0b1000001ต ทั้งหมดมาจากไบต์เดียวกันในตำแหน่งหน่วยความจำเดียวกัน ในภาษา C คุณสามารถเห็นเอฟเฟกต์นี้โดยการชี้ไปที่ประเภทต่าง ๆ เหล่านี้

เมื่อคุณมี "บัฟเฟอร์มากเกินไป" คุณกำลังทำอะไรบางอย่างนอกขอบเขตของสิ่งที่คอมไพเลอร์หรือภาษาของคุณอาจคาดหวัง แต่เท่าที่ฮาร์ดแวร์เกี่ยวข้อง1คุณกำลังเขียนไบต์ (ไม่ว่าเดียวหรือหลาย) ไปยังตำแหน่งหน่วยความจำ ตำแหน่งหน่วยความจำไม่มี "ประเภท" ในความเป็นจริงฮาร์ดแวร์ไม่ทราบด้วยซ้ำว่าชุดไบต์ใด ๆ ที่สร้างอาร์เรย์หรือบัฟเฟอร์ในรหัสของคุณ

ทุกครั้งที่คุณเข้าถึงตำแหน่งหน่วยความจำในรหัสของคุณคำแนะนำจะทำงานตามที่กำหนดไว้ในตอนแรก เช่นถ้าพวกเขาคาดหวังว่าจะมีตัวเลขพวกเขาจะทำอะไรกับไบต์ของข้อมูลราวกับว่าพวกเขาเป็นตัวเลข


หากต้องการใช้ตัวอย่างสมมติว่าคุณintเป็นจำนวนเต็ม 4 ไบต์ (32- บิต) ที่ได้รับการรับรอง:

+-------------+--------------------------------------------+-----------+
| Source code |                  char[15]                  |    int    |
+-------------+--------------------------------------------------------+
| Memory      |61|61|61|62|62|62|63|63|63|64|64|64|65|65|65|EF|BE|AD|DE|
+-------------+--------------------------------------------------------+

คุณจะเห็นว่าintที่ตั้งของหน่วยความจำ 's ตอนนี้มี0xEFBEADDEสมมติว่า big-ระบบ2 นี่คือ int แบบ 32 บิตที่ลงนาม-272716322แล้ว ทีนี้ถ้าคุณตีความหน่วยความจำเดียวกันกับ int ( uint) ที่ไม่ได้ลงชื่อมันจะเป็น4022250974เช่นนั้นแทน สำหรับข้อมูลเดียวกันในหน่วยความจำความหมายนั้นขึ้นอยู่กับว่าคุณดูอย่างไร


1มีกลไกบางอย่างที่ป้องกันไม่ให้คุณเขียนลงในพื้นที่ป้องกันของหน่วยความจำและจะทำให้โปรแกรมของคุณทำงานล้มเหลวหากคุณพยายามทำเช่นนั้น

2 x86 จริง ๆ แล้วเป็น endian น้อยซึ่งหมายความว่าคุณตีความไบต์ที่ทำขึ้นค่าย้อนหลัง ดังนั้นใน x86 คุณควรที่จะ0xDEADBEEFให้ลงชื่อ-559038737หรือไม่ได้ลงนาม3735928559แทน


ดังนั้น0xdeadbeefในสถาปัตยกรรม x86 จะใช้พื้นที่ในหน่วยความจำน้อยกว่าทศนิยมคู่3735928559หรือไม่?
Darien Springer

2
@DarienSpringer ทั้งคู่ใช้หน่วยความจำ 4 ไบต์ขึ้นไป - เป็นลำดับ 4 ไบต์เดียวกัน พวกเขาเหมือนกันในหน่วยความจำ คุณสามารถพิจารณาว่าทั้งหมดจะเป็นฐาน 2 (ไบนารี) ในหน่วยความจำหากคุณต้องการ จากนั้นเมื่อคุณแสดง (แปลงเป็นสตริงสำหรับเอาต์พุต) คุณสามารถเลือกฐานที่จะแสดง - ฐานสิบหกคือฐาน 16 และฐานสิบคือฐาน 10 การแทนค่าสตริงจะถูกเก็บไว้ในตำแหน่งหน่วยความจำที่แตกต่างกันและสามารถใช้จำนวนที่แตกต่างกัน ของหน่วยความจำ (เนื่องจากอักขระแต่ละตัวเป็นไบต์แยกต่างหาก) สตริง ถูกเก็บไว้ในหน่วยความจำ0xDEADBEEF 0x30 0x78 0x44 0x45 0x41 0x44 0x42 0x45 0x45 0x46
บ๊อบ

5
@DarienSpringer ใส่อีกวิธีหนึ่งหมายเลขนั้นคือหมายเลขเดียวกันไม่ว่าจะเป็นฐานใดก็ตาม Hex เป็นวิธีที่สะดวก (กะทัดรัด) ในการดูไบนารี ร่างกายมันเป็นเลขฐานสอง มนุษย์เช่นทศนิยมเรามักแสดงตัวเลขเป็นทศนิยม แต่จนกว่าเราจะไปถึงขั้นตอนการแสดงผลการดำเนินการเชิงตัวเลขทั้งหมด (บวกลบคูณและอื่น ๆ ) จะทำงานกับข้อมูลไบนารีเดียวกันในหน่วยความจำ
บ๊อบ

1
"คุณจะเห็นว่าที่ตั้งของหน่วยความจำ int คือตอนนี้ 0xEFBEADDE" nitpick: ฉันรู้ว่าคุณไม่ได้ตั้งใจที่นี้ แต่ดูเหมือนคุณกำลังจะบอกว่า int ตั้งอยู่ที่0xEFBEADDEสถานที่ตั้งของหน่วยความจำ บางทีคำพูดที่ว่าเล็กน้อย มิฉะนั้นนี่คือคำตอบที่ยอดเยี่ยม - ฉันชอบความคล้ายคลึง "มุมมอง" และ "squinting" ความคิด :)
Lightness Races ใน Orbit

@LightnessRacesinOrbit จุดดี แก้ไข
Bob

2

จากมุมมองของ C คำตอบคือ "ใครจะรู้? มันเป็นพฤติกรรมที่ไม่ได้กำหนด"

ประเภทเป็นแนวคิด C ไม่ใช่ฮาร์ดแวร์ แต่กฎ C จะไม่มีผลหากโปรแกรมของคุณมีพฤติกรรมที่ไม่ได้กำหนดนั่นคือความหมายที่แท้จริงของพฤติกรรมที่ไม่ได้กำหนดในมาตรฐาน C และบัฟเฟอร์โอเวอร์โฟลว์เป็นหนึ่งในนั้น

ฉันเริ่มเขียนว่า "กฎ C ใช้ไม่ได้อีกต่อไป" แต่อันที่จริงพฤติกรรมที่ไม่ได้กำหนดนั้นมีผลย้อนหลัง กฎ C ไม่สามารถใช้กับโปรแกรมที่จะมีพฤติกรรมที่ไม่ได้กำหนดในอนาคต

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.