সি ভাষায় স্ট্রিং ইনপুট আউটপুটের জন্য gets() এবং puts() ব্যবহার করলে প্রোগ্রাম ঠিকঠাক চলে। কিন্তু বিল্ড লগ (Build log) এ ওয়ার্নিং দেখায় এই ফাংশন দুটো নাকি বিপজ্জনক। অর্থাৎ নিচের মত একটি লেখা আসে,

string array.c||warning: the `gets' function is dangerous and should not be used.

আমার প্রশ্ন হল এই ফাংশন দুটো কেন বিপজ্জনক ফাংশন?

asked 30 Jan, 11:15

Rahim_10's gravatar image

Rahim_10
111

edited 30 Jan, 14:52

Mosharraf%20Hosain's gravatar image

Mosharraf Hosain ♦
23618

gets() ফাংশনটি ২০১১ সালে আনুষ্ঠানিকভাবে সি'র স্ট্যান্ডার্ড লাইব্রেরি থেকে বাদ দেয়া হয়েছে এবং সি++ এ এর ব্যবহার নিরুৎসাহিত করা হয়েছে। (সাধারণত) এটি ব্যবহারের কোনো প্রয়োজন নেই।

(30 Jan, 14:49) Mosharraf Hosain ♦

puts() বিপজ্জনক নয়। এর ব্যবহারে ওয়ার্নিং দিবে না।

(01 Feb, 04:48) Ashfaqur Rahman

gets() ফাংশন যেটা করে সেটা হচ্ছে ইনপুট স্ট্রিম থেকে লাইন ফিড (নিউ লাইন ক্যারেক্টার) বা EOF পাওয়ার আগ পর্যন্ত ক্যারেক্টার নিয়ে সেটা একটা ক্যারেক্টার বাফারে রাখে এবং শেষে একটা NULL('\0') জুড়ে দেয়। সমস্যা হচ্ছে gets() ব্যবহার করলে আগে থেকে জানার উপায় থাকে না বাফারে কতগুলো ক্যারেক্টার রাখা হবে। ইউজার যাই ইনপুট দেবে gets() তাই নেবে এবং যদি ইউজারের ইনপুট সাইজ বাফারের সাইজের তুলনায় বেশি হয় সেটাও gets() বাফারে রাখার চেষ্টা করবে। নিচের প্রোগ্রামটি দিয়ে আমি ব্যাপারটা ব্যাখ্যা করছি:

#include <stdio.h>

int main(){
    /* Character buffer of size 5 */
    char buffer[5];
    char number = 65;

    /* gets asking for characters from input stream */
    gets(buffer);

    /* Will print the buffer in output stream*/
    printf("%s\n", buffer);
    printf("%d\n", number);

    return 0;
}

প্রোগ্রামটা চালাচ্ছিঃ

[email protected]:~$ ./bo 
moon
moon
65

[email protected]:~$ ./bo 
programabad
programabad
97

প্রথম ক্ষেত্রে আমি চারটি ক্যারেক্টার ইনপুট দিয়েছি। gets() চারটি ক্যারেক্টার নিয়েছে এবং শেষে NULL যুক্ত করে বাফারে রেখেছে। সেই বাফারটি পরে আবার প্রিন্ট করা হয়েছে এবং number ভ্যারিয়েবল এর ভ্যালু 65 প্রিন্ট করেছে। সবকিছু ঠিক আছে। কিন্তু দ্বিতীয় ক্ষেত্রে আমি বারোটি ক্যারেক্টার ইনপুট দিয়েছি এবং gets() কিন্তু বারোটি ক্যারেক্টারই নিয়েছে এবং শেষে NULL জুড়ে দিয়েছে। তাহলে মোট হল তেরোটি। এই তেরোটি ক্যারেক্টারই কিন্তু সে বাফারে রেখেছে! যদিও বাফারের সাইজ পাঁচ! বাফারটা প্রিন্ট করে আমরা সেটা বুঝতে পারছি। এবং সবচেয়ে ইন্টারেস্টিং ব্যাপারটা হচ্ছে আমাদের number ভ্যারিয়েবল এর ভ্যালু কিন্তু পরিবর্তন হয়ে গেছে! এখন দেখাচ্ছে 97 যেটা আসলে a এর ASCII দশমিক মান। এক্ষেত্রে যেটা হচ্ছে যেহেতু মেমরিতে প্রথমে buffer এর জন্য পাঁচটা জায়গা রাখা এবং পরে number এর জন্য জায়গা রাখা, যখনই আমরা বাফারের সাইজের তুলনায় বেশি ডেটা পাঠাচ্ছি এবং gets() সেটা চেক না করেই বাফারের মেমরিতে রাইট করে ফেলছে। তাই অতিরিক্ত ডেটাগুলো পরের মেমরি ব্লকে জমা হচ্ছে, যে কারণে পাশেই number এর মেমরি ব্লকে a গিয়ে পড়ছে। এটাকে বলে বাফার ওভারফ্লো। আর ঠিক একারণেই gets() খুবই বিপজ্জনক।

gets() ব্যবহার করলে এই বাফার ওভারফ্লোকে কাজে লাগিয়ে কম্পিউটার সিস্টেমে বিভিন্ন ধরনের এটাক করা যেতে পারে যেগুলোকে বাফার ওভারফ্লো এটাক বলে। এই উইকিপিডিয়া আর্টিকেলে বিভিন্ন ধরনের বাফার ওভারফ্লো এটাক সম্পর্কে ধারণা পাওয়া যাবে।

permanent link

answered 01 Feb, 04:46

Ashfaqur%20Rahman's gravatar image

Ashfaqur Rahman
6749

edited 04 Feb, 07:38

Mosharraf%20Hosain's gravatar image

Mosharraf Hosain ♦
23618

Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×374
×17
×6

question asked: 30 Jan, 11:15

question was seen: 159 times

last updated: 04 Feb, 07:38