স্ট্যান্ডার্ড লাইব্রেরি থেকে কোন কাজগুলি অবশ্যই এড়ানো উচিত (উচিত)?


90

আমি স্ট্যাক ওভারফ্লোতে পড়েছি যে কিছু সি ফাংশন "অপ্রচলিত" বা "এড়ানো উচিত"। আপনি দয়া করে আমাকে এই জাতীয় ক্রিয়াকলাপের কয়েকটি কারণ এবং কারণটি দিতে পারেন?

এই ফাংশনগুলির বিকল্পগুলির কি বিদ্যমান?

আমরা সেগুলি নিরাপদে ব্যবহার করতে পারি - কোনও ভাল অনুশীলন?


4
আমি বিশ্বাস করি এটি জানা খুব ভাল জিনিস। সি থেকে কিছু ফাংশন সত্যই এড়ানো এবং কেবল শিক্ষামূলক উদ্দেশ্যে ব্যবহার করা উচিত ।
আইএনএস

@ ফেলিক্স, ভবিষ্যতে একটি একক (সঠিক চিহ্নিত) উত্তর সম্পাদনা করা আরও সহজ হবে। উত্তরগুলির সাথে এটি সত্যই আপ হয় যা সম্ভবত সময়ের সাথে সাথে পরিবর্তিত হবে। কে জানে, সম্ভবত জেফ এমন লোকদের একটি 'দ্বাররক্ষী' ব্যাজ সরবরাহ করবেন যারা পরবর্তী কয়েক বছরে উত্তরগুলি বর্তমান রাখেন।
টিম পোস্ট

4
@ টিম পোস্ট: ঠিক আছে আমি আমার মন্তব্যগুলি মুছব।
ফেলিক্স ক্লিং

4
আমি এর strncpy()জন্য সাধারণ প্রতিস্থাপন হিসাবে ব্যবহার করব না strcpy()এবং আমি strncat()কখনও ব্যবহার করব না কারণ এর কল্পনাযোগ্যভাবে সর্বাধিক অপ্রয়োজনীয় ইন্টারফেস রয়েছে - আপনি কি জানেন দৈর্ঘ্যের প্যারামিটারটি কী নির্দিষ্ট করে?
জোনাথন লেফলার

4
স্ট্রান্সপি এবং স্ট্র্যাঙ্ক্যাট ব্যবহার করা প্রায়শই একটি ভুল। সেগুলি অবশ্যই strcpy এবং strcat এর জায়গায় ব্যবহার করা উচিত নয় !! আপনি কীভাবে কীভাবে এটি ব্যবহার করতে জানেন তা যদি স্ক্যানফ এবং স্প্রিন্টফও পুরোপুরি ব্যবহারযোগ্য হয় ...
আর .. গিটহাব সাহায্যের জন্য বরফ বন্ধ করুন

উত্তর:


58

অননুমোদিত কার্যাবলী
অসুরক্ষিত
একটি যেমন একটি ফাংশন নিখুঁত উদাহরণ পায় () , কোন পথ কিভাবে বড় গন্তব্য বাফার এটা বলতে না থাকায়। ফলস্বরূপ, যে প্রোগ্রামগুলিতে ইনপুট পড়ে তা () ব্যবহার করে একটি বাফার ওভারফ্লো দুর্বলতা থাকে । অনুরূপ কারণে, এক ব্যবহার করা উচিত strncpy () স্থানে strcpy () এবং strncat () স্থানে strcat ()

তবুও আরও কয়েকটি উদাহরণের মধ্যে রয়েছে টেম্পফিল () এবং এমকেটেম্প () ফাংশন অন্তর্ভুক্ত সাময়িক ফাইলগুলি ওভার রাইটিংয়ের সাথে সম্ভাব্য সুরক্ষা সমস্যার কারণে এবং যা আরও সুরক্ষিত এমকেস্টেপ () ফাংশন দ্বারা সরিয়ে দেওয়া হয়।

নন-প্রেরণকারী
অন্যান্য উদাহরণগুলির মধ্যে রয়েছে জেথোস্টবিয়াড্ডার () এবং গেথস্টবাইনেম () যা নন-রিেন্টেন্ট (এবং তাই থ্রেডসেফ হওয়ার গ্যারান্টিযুক্ত নয় ) এবং পুনরায় প্রেরণকারী গেটাড্রিনফো () এবং ফ্রিডাড্রিনফো () দ্বারা বরখাস্ত করা হয়েছে ।

আপনি এখানে কোনও প্যাটার্নটি লক্ষ্য করছেন ... হয় নিরাপত্তার অভাব (সম্ভবত এটি নিরাপদে কার্যকরভাবে প্রয়োগ করতে স্বাক্ষরে যথেষ্ট তথ্য অন্তর্ভুক্ত করতে ব্যর্থ হয়ে) বা পুনরায় প্রবেশ না করা হ্রাসের সাধারণ উত্স।

পুরানো, নন-পোর্টেবল
কিছু অন্যান্য ফাংশন কেবলমাত্র হ্রাস করা হয় কারণ এগুলি কার্যকারিতা সদৃশ করে এবং অন্যান্য রূপগুলির মতো বহনযোগ্য নয়। উদাহরণস্বরূপ, bzero () পক্ষে অবচিত memset ()

থ্রেড সুরক্ষা এবং প্রত্যাবর্তন
আপনি আপনার পোস্টে, থ্রেড সুরক্ষা এবং প্রত্যাবর্তনের বিষয়ে জিজ্ঞাসা করেছিলেন। সামান্য পার্থক্য আছে। কোনও ফাংশন যদি পুনরায় ভাগ করে নেওয়া হয় তবে তা যদি কোনও ভাগ করা, পরিবর্তনীয় স্থিতি ব্যবহার না করে। সুতরাং, উদাহরণস্বরূপ, যদি এটির প্রয়োজনীয় সমস্ত তথ্য যদি ফাংশনে প্রেরণ করা হয় এবং যে কোনও বাফার প্রয়োজন হয় সেগুলি ফাংশনেও প্রেরণ করা হয় (ফাংশনে সমস্ত কল ভাগ করে নেওয়ার চেয়ে) তবে তা পুনরায় প্রেরণকারী। এর অর্থ হ'ল পৃথক থ্রেড, স্বাধীন পরামিতি ব্যবহার করে, ঘটনাক্রমে ভাগ করে নেওয়ার অবস্থা ঝুঁকিপূর্ণ নয়। থ্রেড সুরক্ষার চেয়ে পুনঃপ্রবর্তন একটি শক্তিশালী গ্যারান্টি। কোনও ফাংশনটি থ্রেড নিরাপদ যদি এটি এক সাথে একাধিক থ্রেড ব্যবহার করা যায়। একটি ফাংশন থ্রেড নিরাপদ যদি:

  • এটি প্রেরণকারী (যেমন এটি কলগুলির মধ্যে কোনও রাজ্য ভাগ করে না) বা:
  • এটি পুনঃপ্রেরণকারী নয়, তবে এটি ভাগ করে নেওয়ার জন্য প্রয়োজনীয় হিসাবে সিঙ্ক্রোনাইজেশন / লকিং ব্যবহার করে।

সাধারণভাবে, একক ইউনিক্স স্পেসিফিকেশন এবং আইইইই 1003.1 (অর্থাত্ "পসিক্স"), যে কোনও ক্রিয়াকলাপ যা পুনরায় প্রত্যাবর্তনের গ্যারান্টিযুক্ত নয় তা থ্রেড নিরাপদ থাকার গ্যারান্টিযুক্ত নয়। সুতরাং, অন্য কথায়, কেবলমাত্র ফাংশনগুলি যা প্রত্যাবর্তনের গ্যারান্টিযুক্ত সেগুলি বহুতলযুক্ত অ্যাপ্লিকেশনগুলিতে (বাহ্যিক লকিং ছাড়াই) বহনযোগ্যভাবে ব্যবহৃত হতে পারে। তবে এর অর্থ এই নয় যে এই মানগুলির প্রয়োগগুলি একটি পুনরায় প্রেরণকারী ফাংশন থ্রেডসেফ করতে পছন্দ করতে পারে না। উদাহরণস্বরূপ, থ্রেডসফটিটির গ্যারান্টি (একক ইউনিক্স স্পেসিফিকেশন এর বাইরে) যুক্ত করার জন্য লিনাক্স প্রায়শই পুনঃপ্রেরণকারী ফাংশনে সিঙ্ক্রোনাইজেশন যুক্ত করে।

স্ট্রিংস (এবং মেমোরি বাফারস, সাধারণভাবে)
আপনিও জিজ্ঞাসা করেছিলেন স্ট্রিং / অ্যারেগুলির সাথে কিছু মৌলিক ত্রুটি আছে কিনা। কেউ কেউ তর্ক করতে পারে যে এটিই কেস, তবে আমি যুক্তি দেব যে না, ভাষার কোনও মৌলিক ত্রুটি নেই। সি এবং সি ++ এর জন্য আপনাকে কোনও অ্যারের দৈর্ঘ্য / ক্ষমতা আলাদাভাবে পাস করতে হবে (এটি অন্য কয়েকটি ভাষার মতো "দৈর্ঘ্যের" সম্পত্তি নয়)। এটি কোনও ত্রুটি নয়, প্রতি-সে। যে কোনও সি এবং সি ++ বিকাশকারী যেখানে প্রয়োজন সেখানে প্যারামিটার হিসাবে দৈর্ঘ্য পেরিয়ে সঠিক কোডটি লিখতে পারেন। সমস্যাটি হ'ল বেশ কয়েকটি এপিআই যা এই তথ্যের প্রয়োজন তা প্যারামিটার হিসাবে নির্দিষ্ট করতে ব্যর্থ হয়েছিল। বা ধরে নেওয়া হয়েছে যে কিছু MAX_BUFFER_SIZE ধ্রুবক ব্যবহার করা হবে। এই জাতীয় এপিআইগুলি এখন বিকল্প এপিআই দ্বারা অবচয় এবং প্রতিস্থাপন করা হয়েছে যা অ্যারে / বাফার / স্ট্রিং মাপগুলি নির্দিষ্ট করার অনুমতি দেয়।

স্ক্যান্ফ (আপনার শেষ প্রশ্নের উত্তরে)
ব্যক্তিগতভাবে, আমি সি ++ আইওস্ট্রিম লাইব্রেরি (স্ট্যান্ড :: সিএন, এসটিডি :: কোট, << এবং >> অপারেটর, স্টাড :: গেটলাইন, এসটিডি :: আইসট্রিংস্ট্রিম, স্ট্যান্ড :: অস্ট্রিংস্ট্রিম) ব্যবহার করি , ইত্যাদি), তাই আমি সাধারণত এটি মোকাবেলা করি না। আমি খাঁটি সি ব্যবহার করতে বাধ্য ছিল, যদিও, আমি ব্যক্তিগতভাবে শুধু ব্যবহার করেন fgetc হয় () বা getchar, () একযোগে সঙ্গে strtol () , strtoul () , ইত্যাদি এবং পার্স জিনিষ নিজে, যেহেতু আমি একটি বিশাল অনুরাগী নই varargs বা বিন্যাস স্ট্রিং। এটি বলেছিল, আমার জ্ঞানের সেরা দিক থেকে, [চ] স্ক্যানফ () , [চ] প্রিন্টফ () নিয়ে কোনও সমস্যা নেই, ইত্যাদি। যতক্ষণ আপনি নিজেরাই ফরম্যাটের স্ট্রিং তৈরি করেন ততক্ষণ আপনি কখনই স্বেচ্ছাসেবী বিন্যাসের স্ট্রিংগুলি পাস করেন না বা ব্যবহারকারীর ইনপুটটিকে বিন্যাসের স্ট্রিং হিসাবে ব্যবহার করার অনুমতি দেন না এবং আপনি যেখানে উপযুক্ত << টাইপস>> তে সংজ্ঞায়িত ফর্ম্যাট ম্যাক্রোগুলি ব্যবহার করেন । (নোট, snprintf () স্থানে ব্যবহার করা উচিত , sprintf () , কিন্তু যে গন্তব্য বাফারের মাপ এবং বিন্যাস স্ট্রিং ব্যবহার নির্দিষ্ট করতে ব্যর্থ কি আছে)। আমার আরও উল্লেখ করা উচিত যে, সি ++ এ, বুস্ট :: ফর্ম্যাটটি ভ্যার্যাগগুলি ছাড়াই প্রিন্টফের মতো বিন্যাস সরবরাহ করে।


4
"অবচয়" একটি শক্তিশালী শব্দ, যার সি ++ স্ট্যান্ডার্ড নিয়ে আলোচনা করার একটি নির্দিষ্ট অর্থ রয়েছে। সেই অর্থে, get (), strcpy () ইত্যাদিকে হ্রাস করা হয় না।

4
ঠিক ততক্ষণ আপনি "সি স্ট্যান্ডার্ড দ্বারা অবহেলিত", "মাইকেল অ্যারন সাফিয়ান দ্বারা অবহেলিত" এবং "ব্যক্তি বা অজানা দ্বারা অবহেলিত যারা আশা করছেন যে তারা কী সম্পর্কে বলছেন [প্রশংসা আবশ্যক]" এর মধ্যে পার্থক্য করেন। প্রশ্ন করা হয় সম্পর্কে শৈলী কোডিং না সি মান সম্পর্কে পছন্দের দ্বিতীয় দুই উপযুক্ত তাই। তবে নীলের মতো আমি বুঝতে পারার আগে একটি দ্বিগুণ গ্রহণের দরকার পড়েছিল যে আপনার বক্তব্যটি প্রথম অর্থ বোঝাতে চায় না।
স্টিভ জেসোপ

11
strncpyসাধারণত পাশাপাশি এড়ানো উচিত। এটি বেশিরভাগ প্রোগ্রামাররা এটি করে যা তা করে না। এটি সমাপ্তির গ্যারান্টি দেয় না (বাফারকে ছাড়িয়ে যায়) এবং এটি ছোট স্ট্রিংগুলি প্যাড করে (সম্ভবত কিছু ক্ষেত্রে পারফরম্যান্সকে হ্রাস করে)।
অ্যাড্রিয়ান ম্যাকার্থি 22

4
@Adrian: আমি আপনার সাথে একমত - তন্ন তন্ন strncpy()না এমনকি খারাপ strncat()এন-কম রূপগুলো একটি যুক্তিসম্মত প্রতিস্থাপন।
জোনাথন লেফলার

4
এই উত্তরটি "স্ট্রেনকিপি দিয়ে স্ট্রিম্পি প্রতিস্থাপন করুন - কেন জানি না তবে মাইক্রোসফ্ট আমাকে কেন বলেছে" সম্পর্কে বাজে কথা বলে। আরআরএনপিপি কখনই আরআরসিপিপি-র নিরাপদ সংস্করণ হওয়ার কথা নয়! মুখে এটি অনেক বেশি অনিরাপদ। দেখুন কেন strlcpy এবং strlcatটিকে নিরাপত্তাহীন বলে বিবেচনা করা হচ্ছে?
লন্ডিন

24

লোকেরা আবারও পুনরাবৃত্তি করছে, মন্ত্রের মতো, হাস্যকর বক্তব্য যে স্ট্রং ফাংশনগুলির "এন" সংস্করণটি নিরাপদ সংস্করণ।

যদি তাদের জন্য এটিই উদ্দেশ্য ছিল তবে তারা সর্বদা স্ট্রিংগুলি বাতিল করবে।

ফাংশনের "এন" সংস্করণগুলি নির্দিষ্ট দৈর্ঘ্যের ক্ষেত্রগুলির সাথে ব্যবহারের জন্য লেখা হয়েছিল (যেমন প্রারম্ভিক ফাইল সিস্টেমে ডিরেক্টরি এন্ট্রি) যেখানে স্ট্রিংটি ফিল্ডটি পূরণ না করে কেবল তখনই নুল টার্মিনেটর প্রয়োজন। ফাংশনগুলির অদ্ভুত পার্শ্ব প্রতিক্রিয়াগুলির কারণও এটি কারণ যা কেবল প্রতিস্থাপন হিসাবে ব্যবহৃত হলে নিরর্থকভাবে অক্ষম - স্ট্র্যানকিপি () নিন: উদাহরণস্বরূপ:

যদি এস 2 দ্বারা নির্দেশিত অ্যারে যদি একটি স্ট্রিং হয় যা এন বাইটের চেয়ে কম হয় তবে নাল বাইটগুলি এস -1 দ্বারা নির্দেশিত অ্যারেতে অনুলিপিটি সংযুক্ত করা হবে, যতক্ষণ না সমস্ত এন বাইট না লেখা হয়।

ফাইল নামগুলি হ্যান্ডেল করার জন্য বরাদ্দকৃত বাফারগুলি সাধারণত 4 কেবিট হওয়ায় এটি কার্য সম্পাদনে ব্যাপক অবনতি ঘটাতে পারে।

আপনি যদি "অনুমিত" নিরাপদ সংস্করণগুলি চান তবে আপনার নিজের - strl রুটিনগুলি (strlcpy, strlcat ইত্যাদি) প্রাপ্ত করুন বা লিখুন যা সর্বদা স্ট্রিংগুলি বাতিল করে দেয় এবং এর কোনও পার্শ্ব প্রতিক্রিয়া নেই। দয়া করে মনে রাখবেন যে এগুলি সত্যই নিরাপদ নয় কারণ তারা নিঃশব্দে স্ট্রিংটি কেটে ফেলতে পারে - এটি কোনও বাস্তব-বিশ্ব প্রোগ্রামের ক্ষেত্রে খুব কমই সেরা কর্মকাণ্ড। এমন ঘটনা আছে যেখানে এটি ঠিক আছে তবে এমন অনেকগুলি পরিস্থিতি রয়েছে যেখানে এটি বিপর্যয়কর ফলাফলের দিকে নিয়ে যেতে পারে (যেমন মেডিকেল প্রেসক্রিপশনগুলি মুদ্রণ করে)।


4
আপনি সম্পর্কে সঠিক strncpy(), কিন্তু সম্পর্কে ভুল strncat()strncat()স্থির দৈর্ঘ্যের ক্ষেত্রগুলির সাথে ব্যবহারের জন্য ডিজাইন করা হয়নি - এটি আসলে এমনভাবে তৈরি করা হয়েছিল strcat()যা সংক্ষিপ্ত অক্ষরের সংখ্যা সীমাবদ্ধ করে। strcat()একাধিক বক্তব্য রাখার সময় বাফারের অবশিষ্ট স্থানটি ট্র্যাক করে "নিরাপদ " হিসাবে এটি ব্যবহার করা বেশ সহজ এবং এটি "নিরাপদ strcpy()" হিসাবে ব্যবহার করা আরও সহজ (গন্তব্য বাফারের প্রথম অক্ষরকে '\0'আগে স্থাপন করে) এটি কল করা)। strncat() সর্বদা গন্তব্য স্ট্রিংটি বন্ধ করে দেয় এবং এটি অতিরিক্ত '\0'গুলি লিখেনি।
ক্যাফে

4
@ ক্যাফ - হ্যাঁ তবে স্ট্রান্সক্যাট () সম্পূর্ণ অনর্থক কারণ এটি প্যারামিটার হিসাবে অনুলিপি করতে সর্বাধিক দৈর্ঘ্যের প্রয়োজন - গন্তব্য বাফারের দৈর্ঘ্য নয়। বাফার ওভারফ্লো রোধ করতে আপনার বর্তমান গন্তব্য স্ট্রিংয়ের দৈর্ঘ্য জানতে হবে এবং আপনি যদি জানেন যে আপনি কেন স্ট্রেনক্যাট () ব্যবহার করবেন - যা কেবলমাত্র স্ট্রালক্যাট () এর উত্সের স্ট্রিংয়ের পরিবর্তে এটি ব্যবহার করতে হবে - গন্তব্য স্ট্রিংয়ের সমাপ্তি।
ডিপস্টিক

এটি এখনও এই সত্যটি পরিবর্তন করে না যে আপনি বোঝাচ্ছেন যে strncat()গন্তব্যটি সর্বদা বাতিল করে না, এবং এটি স্থির দৈর্ঘ্যের ক্ষেত্রগুলি ব্যবহারের জন্য তৈরি করা হয়েছিল, উভয়ই ভুল।
ক্যাফে

4
@ ক্রিশারিস: strncat()উত্সের স্ট্রিংয়ের দৈর্ঘ্য নির্বিশেষে সঠিকভাবে কাজ করবে, যদিও strcat()হবে না। এখানে সমস্যা strlcat()হ'ল এটি কোনও স্ট্যান্ডার্ড সি ফাংশন নয়।
ডেভিড থর্নলে

@caf - আপনি strncat () সম্পর্কে সঠিক। আমি আসলে এটি কখনই ব্যবহার করি নি কারণ - যেমন আমি উপরে উল্লেখ করেছি - এটি সম্পূর্ণ অকেজো। এটি এখনও এড়ানো উচিত।
ডিপস্টিক

19

এখানে বেশ কিছু উত্তর ব্যবহার করার সুপারিশ strncat()উপর strcat(); আমি পরামর্শ দিই যে strncat()(এবং strncpy()) এড়ানোও উচিত। এটিতে এমন সমস্যা রয়েছে যা সঠিকভাবে ব্যবহার করা এবং বাগগুলি বাড়ে:

  • দৈর্ঘ্যের প্যারামিটার strncat()সম্পর্কিত (তবে একেবারে ঠিক নয় - তৃতীয় পয়েন্টটি দেখুন) গন্তব্য বাফারের আকারের চেয়ে গন্তব্যটিতে অনুলিপি করা যায় এমন সর্বাধিক সংখ্যক অক্ষর। এটি strncat()যতটা হওয়া উচিত তার চেয়ে ব্যবহার করা আরও বেশি কঠিন করে তোলে , বিশেষত যদি একাধিক আইটেম গন্তব্য পর্যন্ত সংযুক্ত করা হয়।
  • ফলাফলটি কাটা হয়েছে কিনা তা নির্ধারণ করা কঠিন হতে পারে (যা গুরুত্বপূর্ণ হতে পারে বা নাও হতে পারে)
  • একের পর এক ত্রুটি থাকা সহজ। C99 স্ট্যান্ডার্ড নোট হিসাবে, "এইভাবে, অ্যারে নির্দেশিত অ্যারেতে শেষ হতে পারে এমন সর্বাধিক সংখ্যক s1হ'ল strlen(s1)+n+1" কলটির মতো দেখায়strncat( s1, s2, n)

strncpy()এছাড়াও একটি সমস্যা রয়েছে যার ফলে আপনি বাগটিকে স্বজ্ঞাত উপায়ে এটি ব্যবহার করার চেষ্টা করতে পারেন - এটি গ্যারান্টি দেয় না যে গন্তব্যটি বাতিল হবে। আপনি '\0'বাফারের সর্বশেষ স্থানে নিজেই (কমপক্ষে কিছু নির্দিষ্ট পরিস্থিতিতে) একটি ড্রপ ফেলে আপনি নিশ্চিত হয়েছেন যে আপনি নির্দিষ্টভাবে সেই কোণার কেসটি পরিচালনা করেছেন ensure

আমি ওপেনবিএসডি এর মতো কিছু ব্যবহার করার পরামর্শ দেব strlcat()এবং strlcpy()(যদিও আমি জানি যে কিছু লোক এই ফাংশনগুলি অপছন্দ করে; আমি বিশ্বাস করি যে তারা strncat()/ / এর চেয়ে নিরাপদে ব্যবহার করা আরও সহজ strncpy())।

এখানে কি টড মিলার এবং থিও ডি Raadt সমস্যা সম্পর্কে বলার ছিল একটি সামান্য ব্যাপার strncat()এবং strncpy():

সেখানে বেশ কিছু সমস্যা সম্মুখীন যখন হয় strncpy()এবং strncat()নিরাপদ সংস্করণ হিসাবে ব্যবহৃত হয় strcpy()এবং strcat()। উভয় ফাংশনই NUL- সমাপ্তি এবং দৈর্ঘ্য পরামিতি বিভিন্ন এবং অ-স্বজ্ঞাত উপায়ে মোকাবেলা করে যা অভিজ্ঞ প্রোগ্রামারগুলিকেও বিভ্রান্ত করে। এগুলি যখন কাটা কাটা ঘটে তখন সনাক্ত করার কোনও সহজ উপায়ও দেয় না। ... এই সমস্ত সমস্যার মধ্যে দৈর্ঘ্যের পরামিতিগুলির কারণে সৃষ্ট বিভ্রান্তি এবং NUL- সমাপ্তির সম্পর্কিত সমস্যাটি সবচেয়ে গুরুত্বপূর্ণ। আমরা যখন সম্ভাব্য নিরাপত্তা গর্ত জন্য OpenBSD উৎস গাছ নিরীক্ষা আমরা প্রচণ্ড অপব্যবহার পাওয়া strncpy()এবং strncat()। যদিও এর সবগুলিই ব্যবহারযোগ্য সুরক্ষা গর্তের ফলস্বরূপ নয়, তারা এটি পরিষ্কার করে দিয়েছিল যে নিরাপদ স্ট্রিং অপারেশনগুলি ব্যবহার strncpy()এবং ব্যবহারের নিয়মগুলি strncat()ব্যাপকভাবে ভুল বোঝাবুঝি।

ওপেনবিএসডি-র সুরক্ষা নিরীক্ষণে দেখা গেছে যে এই ফাংশনগুলির সাথে বাগগুলি "প্রচণ্ড" ছিল। বিপরীতে gets(), এই ফাংশনগুলি নিরাপদে ব্যবহার করা যেতে পারে, তবে অনুশীলনে অনেকগুলি সমস্যা রয়েছে কারণ ইন্টারফেসটি বিভ্রান্তিমূলক, অজ্ঞাত এবং সঠিকভাবে ব্যবহার করা কঠিন difficult আমি জানি যে মাইক্রোসফ্টও বিশ্লেষণ করেছে (যদিও আমি জানি না যে তারা তাদের কতটা তথ্য প্রকাশ করেছে) এবং ফলস্বরূপ নিষিদ্ধ করেছে (বা কমপক্ষে খুব জোরালোভাবে নিরুৎসাহিত হয়েছে - 'নিষেধাজ্ঞাগুলি পরম হতে পারে না)' ব্যবহারের strncat()এবং strncpy()(অন্যান্য কার্যাবলী মধ্যে)।

আরও তথ্যের সাথে কিছু লিঙ্ক:


4
স্ট্রিংয়ের বাইরে স্ট্রিংয়ের দৈর্ঘ্যের উপর নজর রাখা আরও বেশি ভাল। এর মতো, দুটি স্ট্রিং (-দৈর্ঘ্য সহ) সুরক্ষিত করা একটি সহজ গণনা (প্রয়োজনীয় বাফার আকার পেতে) একটি সম্ভাব্য পুনঃনির্ধারণের বিষয়টি হয়ে যায় এবং এ memmove()। (ভাল, memcpy()স্ট্রিংগুলি স্বতন্ত্র হলে আপনি সাধারণ ক্ষেত্রে ব্যবহার করতে পারেন ))
ডোনাল ফেলো

4
আপনার দ্বিতীয় পয়েন্টটি ভুল মারা গেছে - strncat() সর্বদা গন্তব্যের স্ট্রিংটি বন্ধ করে দেয়।
ক্যাফে

4
আপনার দ্বিতীয় পয়েন্ট ভুল strncat()। তবে এটি সঠিক strncpy(), এতে আরও কিছু সমস্যা রয়েছে। strncat()এর জন্য একটি যুক্তিসঙ্গত প্রতিস্থাপন strcat(), তবে strncpy()এটির পক্ষে যুক্তিসঙ্গত প্রতিস্থাপন নয় strcpy()
ডেভিড থর্নলি

4
ক্যাফে এবং ডেভিড আমার দাবির বিষয়ে 100% সঠিক যেটি strncat()সর্বদা বাতিল হয় না। আমি আচরণগুলি strncat()এবং strncpy()কিছুটা বিভ্রান্ত করেছিলাম (তারা এড়াতে ফাংশনগুলির আরেকটি কারণ - তাদের এমন নাম রয়েছে যা একই আচরণগুলি বোঝায়, তবে বাস্তবে গুরুত্বপূর্ণ উপায়ে আলাদাভাবে আচরণ করে ...)। আমি এই উত্তরটি সংশোধন করার পাশাপাশি অতিরিক্ত তথ্য যুক্ত করার জন্য আমার উত্তরটি সংশোধন করেছি।
মাইকেল বুড়

4
দ্রষ্টব্য যে char str[N] = ""; strncat(str, "long string", sizeof(str));এন যথেষ্ট পরিমাণে বড় না হলে একটি বাফার ওভারফ্লো। strncat()ফাংশন অপব্যবহার খুব সহজ; এটি ব্যবহার করা উচিত নয়। আপনি যদি strncat()নিরাপদে ব্যবহার করতে পারেন তবে আপনি ব্যবহার করতে পারেন memmove()বা memcpy()পরিবর্তে (এবং সেগুলি আরও কার্যকর হবে)।
জোনাথন লেফলার 15

9

স্ট্যান্ডার্ড গ্রন্থাগার ফাংশন যা কখনও ব্যবহার করা উচিত নয় :

setjmp.h

  • setjmp()। একসাথে longjmp(), এই ফাংশনগুলি ব্যাপকভাবে ব্যবহার করা অবিশ্বাস্যরূপে বিপজ্জনক হিসাবে স্বীকৃত: এগুলি স্প্যাগেটি প্রোগ্রামিংয়ের দিকে পরিচালিত করে, তারা বিভিন্ন ধরণের অপরিজ্ঞাত আচরণের সাথে আসে, তারা প্রোগ্রামের পরিবেশে অনিচ্ছাকৃত পার্শ্ব-প্রতিক্রিয়া সৃষ্টি করতে পারে, যেমন স্ট্যাকের উপর সঞ্চিত মূল্যবোধকে প্রভাবিত করে। তথ্যসূত্র: MISRA-C: 2012 বিধি 21.4, সিইআরটি সি এমএসসি 22-সি
  • longjmp()। দেখুন setjmp()

stdio.h

  • gets()। ফাংশনটি সি ভাষা থেকে সরানো হয়েছে (সি 11 অনুসারে), কারণ এটি নকশা অনুযায়ী অনিরাপদ ছিল। ফাংশনটি ইতিমধ্যে C99 এ অপ্রচলিত হিসাবে চিহ্নিত করা হয়েছিল। fgets()পরিবর্তে ব্যবহার করুন। তথ্যসূত্র: আইএসও 9899: 2011 কে.3.5.4.1, নোট 404 দেখুন।

stdlib.h

  • atoi()ফাংশন পরিবার। এগুলির কোনও পরিচালনা করার ক্ষেত্রে ত্রুটি নেই তবে যখনই ত্রুটি দেখা দেয় তখনই অনির্ধারিত আচরণের আবেদন করুন। সম্পূর্ণরূপে অতিরিক্ত প্রয়োজনযুক্ত ফাংশন যা ফাংশনগুলির strtol()পরিবারের সাথে প্রতিস্থাপন করা যেতে পারে । তথ্যসূত্র: MISRA-C: 2012 বিধি 21.7।

স্ট্রিং

  • strncat()। একটি বিশ্রী ইন্টারফেস রয়েছে যা প্রায়শই অপব্যবহার করা হয়। এটি বেশিরভাগ ক্ষেত্রে একটি অতিরিক্ত কাজকর্ম হয়। জন্য মন্তব্য দেখুন strncpy()
  • strncpy()। এই ফাংশনটির অভিপ্রায়টি কখনই নিরাপদ সংস্করণ হওয়া উচিত ছিল না strcpy()। এর একমাত্র উদ্দেশ্য সর্বদা ছিল ইউনিক্স সিস্টেমগুলিতে একটি প্রাচীন স্ট্রিং ফর্ম্যাটটি পরিচালনা করা এবং এটি স্ট্যান্ডার্ড লাইব্রেরিতে অন্তর্ভুক্ত হওয়া একটি পরিচিত ভুল। এই ফাংশনটি বিপজ্জনক কারণ এটি নাল টার্মিনেশন ছাড়াই স্ট্রিংটি ছেড়ে যেতে পারে এবং প্রোগ্রামাররা প্রায়শই এটি ভুলভাবে ব্যবহার করতে পারে বলে জানা যায়। তথ্যসূত্র: স্ট্র্লকপি এবং স্ট্রলক্যাটকে কেন নিরাপত্তাহীন বলে বিবেচনা করা হয়?

সতর্কতার সাথে ব্যবহার করা উচিত স্ট্যান্ডার্ড গ্রন্থাগার ফাংশন:

assert.h

  • assert()। ওভারহেড সহ আসে এবং সাধারণত উত্পাদন কোড ব্যবহার করা উচিত নয়। কোনও অ্যাপ্লিকেশন-নির্দিষ্ট ত্রুটি হ্যান্ডলার ব্যবহার করা ভাল যা ত্রুটি প্রদর্শন করে তবে অগত্যা পুরো প্রোগ্রামটি বন্ধ করে দেয় না।

সংকেত

  • signal()। তথ্যসূত্র: MISRA-C: 2012 বিধি 21.5, CERT C SIG32-C

stdarg.h

  • va_arg()ফাংশন পরিবার। একটি সি প্রোগ্রামে পরিবর্তনশীল দৈর্ঘ্যের ফাংশনগুলির উপস্থিতি প্রায় সবসময়ই দুর্বল প্রোগ্রাম ডিজাইনের ইঙ্গিত। আপনার খুব নির্দিষ্ট প্রয়োজনীয়তা না থাকলে এড়ানো উচিত।

stdio.h
সাধারণত, এই পুরো লাইব্রেরিটি উত্পাদন কোডের জন্য সুপারিশ করা হয় না , কারণ এটি অসম্পূর্ণ সংজ্ঞায়িত আচরণ এবং দুর্বল ধরণের সুরক্ষার অসংখ্য ক্ষেত্রে আসে।

  • fflush()। আউটপুট স্ট্রিমগুলির জন্য ব্যবহার করার জন্য পুরোপুরি জরিমানা। ইনপুট স্ট্রীমগুলির জন্য ব্যবহার করা হলে অপরিজ্ঞাত আচরণের ডাক দেয়।
  • gets_s()gets()সি 11 বাউন্ডস-চেকিং ইন্টারফেসের অন্তর্ভুক্ত এর নিরাপদ সংস্করণ । এটি fgets()পরিবর্তে সি ব্যবহারের পছন্দ হিসাবে সুপারিশ করা হয়। তথ্যসূত্র: আইএসও 9899: 2011 কে.3.5.4.1।
  • printf()ফাংশন পরিবার। প্রচুর সংজ্ঞায়িত আচরণ এবং দুর্বল ধরণের সুরক্ষা সহ ভারী ফাংশনগুলি রিসোর্স করুন। sprintf()দুর্বলতাও রয়েছে। এই ফাংশনগুলি উত্পাদন কোড এড়ানো উচিত। তথ্যসূত্র: MISRA-C: 2012 বিধি 21.6।
  • scanf()ফাংশন পরিবার। সম্পর্কে মন্তব্য দেখুন printf()। এছাড়াও, - scanf()সঠিকভাবে ব্যবহার না করা হলে বাফারকে ছাড়িয়ে যাওয়ার পক্ষে ঝুঁকি রয়েছে। fgets()সম্ভব হলে ব্যবহার করতে পছন্দ করা হয়। তথ্যসূত্র: CERT C INT05-C , MISRA-C: 2012 বিধি 21.6।
  • tmpfile()ফাংশন পরিবার। বিভিন্ন দুর্বলতার সমস্যা নিয়ে আসে। তথ্যসূত্র: CERT C FIO21-C

stdlib.h

  • malloc()ফাংশন পরিবার। হোস্ট করা সিস্টেমগুলিতে ব্যবহার করার জন্য পুরোপুরি জরিমানা, যদিও C90 তে সুপরিচিত সমস্যাগুলি সম্পর্কে সচেতন থাকুন এবং ফলস্বরূপ ফলটি নিক্ষেপ করবেন নাmalloc()ফাংশন পরিবার অ্যাপ্লিকেশন freestanding কখনও ব্যবহার করা উচিত। তথ্যসূত্র: MISRA-C: 2012 বিধি 21.3।

    এছাড়াও মনে রাখবেন যে realloc()আপনি যদি ফলাফলটির সাথে পুরানো পয়েন্টারটি ওভাররাইট করেন তবে এটি বিপজ্জনক realloc()। যদি ফাংশনটি ব্যর্থ হয় তবে আপনি একটি ফাঁস তৈরি করুন।

  • system()। প্রচুর ওভারহেড নিয়ে আসে এবং পোর্টেবল যদিও এটির পরিবর্তে সিস্টেম-নির্দিষ্ট এপিআই ফাংশন ব্যবহার করা প্রায়শই ভাল। বিভিন্ন খারাপ-সংজ্ঞায়িত আচরণের সাথে আসে। তথ্যসূত্র: CERT C ENV33-C

স্ট্রিং

  • strcat()। জন্য মন্তব্য দেখুন strcpy()
  • strcpy()। ব্যবহার করার জন্য পুরোপুরি জরিমানা, অনুলিপি করা না হওয়া অবধি ডেটা আকার না জানা বা গন্তব্য বাফারের চেয়ে বড়। যদি আগত ডেটার আকারের কোনও চেক না করা হয়, তবে সেখানে বাফার ওভারআনস হতে পারে। যার কোন দোষ strcpy()নিজেই কিন্তু কলিং আবেদন - যে strcpy()অনিরাপদ বেশিরভাগই হয় একটা শ্রুতি মাইক্রোসফট দ্বারা নির্মিত
  • strtok()। কলারের স্ট্রিংকে পরিবর্তন করে এবং অভ্যন্তরীণ রাষ্ট্রের ভেরিয়েবলগুলি ব্যবহার করে, যা এটি বহু-থ্রেডযুক্ত পরিবেশে অনিরাপদ তৈরি করতে পারে।

আমি স্থিতিশীল static_assert()জায়গায় পরামর্শ দেওয়ার পরামর্শ দিচ্ছি assert(), যদি শর্তটি সংকলনের সময়ে সমাধান করা যায়। এছাড়াও, sprintf()প্রায় সর্বদা প্রতিস্থাপন করা যায় snprintf()যা কিছুটা নিরাপদ।
ব্যবহারকারী 694733

4
strtok()একটি ফাংশন এ ব্যবহার করার অর্থ হ'ল (ক) ফাংশন অন্য কোনও ফাংশনকে কল করতে পারে না যা এ ব্যবহার করার strtok()সময় ব্যবহার করে, এবং (খ) এর অর্থ এই যে কোন ফাংশন যা এ কল করে strtok()এটি যখন এ ডবে তখন এটি ব্যবহার করতে পারে না অন্য কথায়, ব্যবহার করে strtok()কল চেইনের বিষকে; এটি লাইব্রেরি কোডে নিরাপদে ব্যবহার করা যাবে না কারণ এটি অবশ্যই নথির নথি যা strtok()অন্য ব্যবহারকারীদের strtok()লাইব্রেরি কোডটি কল করতে বাধা দেওয়ার জন্য ব্যবহার করে ।
জোনাথন লেফলার

strncpyসঠিক ফাংশন একটি zero- লেখা ব্যবহার করা প্যাডেড হয় একটি শূন্য-সমাপ্ত স্ট্রিং বা একটি শূন্য-প্যাডেড বাফার যার আকার গন্তব্য মত বৃহৎ অন্তত থেকে নিয়ে যাওয়া তথ্য দিয়ে স্ট্রিং বাফার। জিরো প্যাডযুক্ত বাফারগুলি মারাত্মক সাধারণ নয়, তবে সেগুলিও ঠিক অস্পষ্ট নয়।
সুপারক্যাট

7

কিছু মানুষ যে দাবি করবে strcpyএবং strcatপক্ষে, এড়িয়ে চলা উচিত strncpyএবং strncat। এটি আমার মতে কিছুটা সাবজেক্টিভ।

ব্যবহারকারীর ইনপুট নিয়ে কাজ করার সময় এগুলি অবশ্যই এড়ানো উচিত - এখানে কোনও সন্দেহ নেই।

ব্যবহারকারীর কাছ থেকে "দূরে" কোডে, আপনি যখন জানবেন যে বাফারগুলি যথেষ্ট দীর্ঘ, strcpyএবং strcatএটি আরও কিছুটা দক্ষ হতে পারে কারণ nতাদের কাজিনের কাছে পাস করার জন্য কম্পিউটিংটি অতিরিক্ত অতিরিক্ত হতে পারে।


4
এবং যদি উপলভ্য থাকে তবে আরও ভাল strlcatএবং strlcpy, যেহেতু 'এন' সংস্করণটি গন্তব্যের স্ট্রিংয়ের NULL সমাপ্তির গ্যারান্টি দেয় না।
ড্যান অ্যান্ড্রিটা

আমার কাছে অকাল অপ্টিমাইজেশনের মতো শোনাচ্ছে। তবে আইআইআরসি, strncpy()লিখতে হবে ঠিক nবাইট, প্রয়োজনে নুল অক্ষর ব্যবহার করে। ড্যান হিসাবে, একটি নিরাপদ সংস্করণ ব্যবহার করা সেরা পছন্দ আইএমও।
বাসটিয়েন লোনার্ড

@ ড্যান, এই ফাংশনগুলি দুর্ভাগ্যক্রমে মানহীন, এবং তাই এই আলোচনার সাথে সম্পর্কিত নয়
এলি বেন্ডারস্কি

@ এলি: তবে strncat()সঠিক এবং নিরাপদে ব্যবহার করা (এবং এড়ানো উচিত) বিষয়টি বিষয়টিতে রয়েছে ।
মাইকেল বুড়

@ মিশেল: আমি বলব না সঠিক এবং নিরাপদে ব্যবহার করা কঠিন difficult যত্ন সহকারে, এটি ঠিক কাজ করে
এলি বেন্ডারস্কি

6

এড়াতে

  • strtok মাল্টিথ্রেডেড প্রোগ্রামগুলির জন্য এটি থ্রেড-নিরাপদ নয়।
  • gets এটি বাফার ওভারফ্লো হতে পারে

4
এগুলি কিছুটা আলাদা কেস। আপনি যদি জানতে পারেন যে আপনার প্রোগ্রামটি মাল্টিথ্রেডেড নয় বা আপনি কোনওভাবে এতে অ্যাক্সেস লক করেছেন তবে আপনি নিরাপদে ব্যবহার করতে পারবেন না তাই এটি কখনই ব্যবহার করা উচিত নয়।
jcoder

9
সমস্যাটি strtok()থ্রেড সুরক্ষার বাইরে কিছুটা অতিক্রম করে - এটি একক থ্রেডেড প্রোগ্রামেও নিরাপদ নয় যদি না আপনি নিশ্চিত জানেন যে ব্যবহারের সময় আপনার কোডটি কল করতে পারে strtok()না তবে এটি ব্যবহার করবেন না (বা তারা strtok()রাজ্যকে জবাবদিহি করবে) আপনার অধীনে থেকে)। প্রকৃতপক্ষে, বেশিরভাগ সংকলক যারা মাল্টি-থ্রেড প্ল্যাটফর্মগুলিকে লক্ষ্য strtok()করে তাদের strtok()স্ট্যাটিক ডেটার জন্য থ্রেড-লোকাল স্টোরেজ ব্যবহার করে থ্রেডগুলি যতটা সম্ভব সমস্যাগুলির যত্ন নেয় । তবে এটি আপনার থাকা অবস্থায় (একই থ্রেডে) থাকা অবস্থায় এটি ব্যবহার করে অন্যান্য ফাংশনগুলির সমস্যা এখনও ঠিক করে না।
মাইকেল বুড়

প্রকৃতপক্ষে এবং আমি এখন চুপ করে যাব কারণ আমি কাউকে স্ট্রটোক ব্যবহার করতে উত্সাহিত করতে চাই না কারণ এটি অনেক সমস্যায় ভুগছে। আমি কেবল এটি চিহ্নিত করতে চেয়েছিলাম যে এটি লাভের চেয়ে আলাদা যদিও এটি নিরাপদে ব্যবহার করা সম্ভব যেখানে নিরাপদভাবে ব্যবহার করা অসম্ভব।
jcoder

@ জিমি: প্রায়শই নন-স্ট্যান্ডার্ড লাইব্রেরি এক্সটেনশন হয় বা আপনি নিজের লেখা লিখতে পারেন। বড় সমস্যাটি strtok()হ'ল এটি কাজ করার জন্য এক বারের বাফারকে ঠিক রাখে, তাই বেশিরভাগ ভাল প্রতিস্থাপনের জন্য একটি বাফারের মান রাখা এবং এটি পাস করা দরকার
ডেভিড থর্নলি

strcspnআপনার যা প্রয়োজন তা সর্বাধিক করে - পরবর্তী টোকেন বিভাজকটি সন্ধান করুন। আপনি এর strtokসাথে একটি বুদ্ধিমান বৈকল্পিক পুনরায় সংশোধন করতে পারেন ।
bluss

5

এটি সম্ভবত যুক্ত করার উপযুক্ত যে এটির নামটি সম্ভবত এটির প্রস্তাব দেয় এটি strncpy()সাধারণ উদ্দেশ্য প্রতিস্থাপন strcpy()নয়। এটি স্থির-দৈর্ঘ্যের ক্ষেত্রগুলির জন্য ডিজাইন করা হয়েছে যার কোনও নুল-টার্মিনেটরের প্রয়োজন নেই (এটি মূলত ইউএনএক্স ডিরেক্টরি ডিরেক্টরিতে প্রবেশের জন্য তৈরি করা হয়েছিল, তবে এনক্রিপশন কী ক্ষেত্রের মতো জিনিসগুলির জন্য দরকারী হতে পারে)।

তবে এর strncat()প্রতিস্থাপন হিসাবে এটি ব্যবহার করা সহজ strcpy():

if (dest_size > 0)
{
    dest[0] = '\0';
    strncat(dest, source, dest_size - 1);
}

( ifপরীক্ষাটি অবশ্যই সাধারণ ক্ষেত্রে বাদ দেওয়া যেতে পারে, যেখানে আপনি জানেন যে dest_sizeএটি অবশ্যই ননজারো)।


5

মাইক্রোসফ্ট নিষিদ্ধ API গুলি তালিকা দেখুন । এগুলি এমন APIs (ইতিমধ্যে এখানে তালিকাভুক্ত অনেকগুলি সহ) মাইক্রোসফ্ট কোড থেকে নিষিদ্ধ কারণ তারা প্রায়শই অপব্যবহার করে এবং সুরক্ষার সমস্যার কারণ হতে পারে।

আপনি তাদের সবার সাথে একমত নাও হতে পারেন, তবে সেগুলি বিবেচনার জন্য। তারা তালিকায় একটি এপিআই যুক্ত করে যখন এর অপব্যবহারের ফলে বেশ কয়েকটি সুরক্ষা বাগ তৈরি হয়েছে।


2

প্রায় কোনও ক্রিয়াকলাপ যা NUL টার্মিনেটেড স্ট্রিংগুলির সাথে সম্পর্কিত সেগুলি সম্ভাব্য অনিরাপদ। যদি আপনি বাইরের বিশ্ব থেকে ডেটা পেয়ে থাকেন এবং স্ট্রিং * () ফাংশনগুলির মাধ্যমে এটি চালিত করে থাকেন তবে আপনি নিজেকে বিপর্যয়ের জন্য সেট আপ করুন


2

স্প্রিন্টফ সম্পর্কে ভুলবেন না - এটি অনেক সমস্যার কারণ। এটি সত্য, কারণ বিকল্প, স্নিপ্রিন্টফের মাঝে মাঝে বিভিন্ন প্রয়োগ থাকে যা আপনাকে কোডটি বহনযোগ্য করে তুলতে পারে।

  1. লিনাক্স: http://linux.die.net/man/3/snprintf

  2. উইন্ডোজ: http://msdn.microsoft.com/en-us/library/2ts7cx93%28VS.71%29.aspx

1 (লিনাক্স) ক্ষেত্রে রিটার্নের মানটি পুরো বাফারটি সংরক্ষণ করার জন্য প্রয়োজনীয় পরিমাণের পরিমাণ (যদি তা প্রদত্ত বাফারের আকারের চেয়ে ছোট হয় তবে আউটপুট কেটে দেওয়া হয়েছিল)

যদি 2 (উইন্ডোজ) ক্ষেত্রে আউটপুট কেটে যায় তবে রিটার্ন মানটি একটি নেতিবাচক সংখ্যা।

সাধারণত আপনার এমন ক্রিয়াগুলি এড়ানো উচিত:

  1. বাফার ওভারফ্লো নিরাপদ (এখানে অনেক ফাংশন ইতিমধ্যে উল্লেখ করা হয়েছে)

  2. থ্রেড নিরাপদ / প্রত্যাবর্তনকারী নয় (উদাহরণস্বরূপ স্ট্রোটোক)

প্রতিটি ফাংশনের ম্যানুয়ালটিতে আপনার কীওয়ার্ডগুলি অনুসন্ধান করা উচিত: নিরাপদ, সিঙ্ক, অ্যাসিঙ্ক, থ্রেড, বাফার, বাগ


4
_sprintf()মাইক্রোসফ্ট স্ট্যান্ডার্ড snprintf()আসার আগেই আইআইআরসি তৈরি করেছিল। ´স্ট্রিংসিবিপ্রিন্টফ () thoughsnprintf() যদিও এর সাথে বেশ মিল ।
বাস্তিয়ান লোনার্ড

আপনি ব্যবহার করতে পারেন sprintfকিছু ক্ষেত্রে নিরাপদে একরকম: sprintf(buffer,"%10s",input);সীমিত কপি দ্রষ্টব্য থেকে 10 বাইট (যদি bufferহয় char buffer[11]এটি নিরাপদ এমনকি যদি ডাটা গুটান পারে ছেঁটে ফেলা।
জাঁ ফ্রাসোয়া Fabre

2

scanfনিরাপদে ব্যবহার করা খুব কঠিন । scanfবাফার ওভারফ্লোগুলি এড়ানো ভাল , তবে আপনি অনুরোধের ধরণের উপযুক্ত নয় এমন নম্বরগুলি পড়ার সময় আপনি অপরিজ্ঞাত আচরণের পক্ষে ঝুঁকির মধ্যে পড়েছেন। বেশিরভাগ ক্ষেত্রেই সালে fgetsস্ব-পার্সিং দ্বারা অনুসরণ (ব্যবহার sscanf, strchrইত্যাদি) একটি ভাল বিকল্প।

তবে আমি "সারাক্ষণ এড়ানো" বলব না scanfscanfএর ব্যবহার আছে। উদাহরণ হিসাবে, ধরা যাক আপনি char10 বাইট লম্বা অ্যারেতে ব্যবহারকারী ইনপুটটি পড়তে চান । আপনি যদি কোনও পূর্ববর্তী নিউলাইনটি সরাতে চান। যদি ব্যবহারকারী কোনও নিউলাইনের আগে 9 টিরও বেশি অক্ষর প্রবেশ করে, আপনি বাফারে প্রথম 9 টি অক্ষর সংরক্ষণ করতে চান এবং পরবর্তী নিউলাইন পর্যন্ত সমস্ত কিছু বাতিল করতে চান। আপনি করতে পারেন:

char buf[10];
scanf("%9[^\n]%*[^\n]", buf));
getchar();

একবার আপনি এই প্রবাদটি অভ্যস্ত হয়ে উঠলে এটি আরও খাটো এবং কিছু উপায়ে পরিষ্কার করুন:

char buf[10];
if (fgets(buf, sizeof buf, stdin) != NULL) {
    char *nl;
    if ((nl = strrchr(buf, '\n')) == NULL) {
        int c;
        while ((c = getchar()) != EOF && c != '\n') {
            ;
        }
    } else {
        *nl = 0;
    }
}

0

সমস্ত স্ট্রিং-অনুলিপি / সরানোর দৃশ্যে - strcat (), strncat (), strcpy (), strncpy (), ইত্যাদি - কিছু দম্পতি সরল হিউরিস্টিকস প্রয়োগ করা হয় তবে জিনিসগুলি আরও ভাল ( নিরাপদ ) হয়:

   1. সর্বদা NUL- পূরণ করুন ডেটা যোগ করার আগে আপনার বাফার (গুলি)।
   ২. ম্যাক্রো-ধ্রুবক সহ [SIZE + 1] হিসাবে অক্ষর-বাফারগুলি ঘোষণা করুন।

উদাহরণস্বরূপ, প্রদত্ত:

#define   BUFSIZE   10
char      Buffer[BUFSIZE+1] = { 0x00 };  /* The compiler NUL-fills the rest */

আমরা কোড ব্যবহার করতে পারি:

memset(Buffer,0x00,sizeof(Buffer));
strncpy(Buffer,BUFSIZE,"12345678901234567890");

তুলনামূলকভাবে নিরাপদে। মেমসেটটি () টি স্ট্রেনকিপি () এর আগে উপস্থিত হওয়া উচিত, যদিও আমরা সংকলন-সময় বাফারটি আরম্ভ করেছিলাম, কারণ আমাদের ফাংশন বলার আগে আমরা অন্যান্য জঞ্জালটিতে কী আবর্জনা রেখেছিলাম তা জানি না। আরআরএনসিপি () অনুলিপি করা তথ্যটিকে "1234567890" এ ছাঁটাই করবে এবং এটি NUL- সমাপ্ত করবে না । তবে, যেহেতু আমরা ইতিমধ্যে বুফসাইজের পরিবর্তে পুরো বাফার - আকার (বাফার) -কে NUL- পূর্ণ করে দিয়েছি - NU- কে যেভাবেই হোক না কেন একটি চূড়ান্ত "আউট-অফ-স্কোপ" হওয়ার নিশ্চয়তা দেওয়া হচ্ছে, যতক্ষণ না আমরা বুশফিজ ব্যবহার করে আমাদের লেখাগুলি সীমাবদ্ধ রাখি না as ধ্রুবক, পরিবর্তে আকারের (বাফার) এর পরিবর্তে।

বাফার এবং বুফসাইজে স্নিপ্রিন্টফ () এর জন্যও সূক্ষ্মভাবে কাজ করে:

memset(Buffer,0x00,sizeof(Buffer));
if(snprintf(Buffer,BUFIZE,"Data: %s","Too much data") > BUFSIZE) {
    /* Do some error-handling */
}   /* If using MFC, you need if(... < 0), instead */

যদিও স্নিপ্রিন্টফ () সুনির্দিষ্টভাবে কেবল বুফিজ -১ টি অক্ষর লিখেছে, তারপরে NUL অনুসরণ করবে, এটি নিরাপদে কাজ করে। সুতরাং আমরা বাফারের শেষে একটি বহির্মুখী NUL বাইট "নষ্ট" করি ... আমরা একটি খুব ছোট স্মৃতি-ব্যয়ের জন্য বাফার-ওভারফ্লো এবং নির্বিঘ্নিত স্ট্রিং শর্ত উভয়কেই প্রতিরোধ করি।

Strcat () এবং strncat () এ আমার কলটি আরও কঠোর-লাইন: সেগুলি ব্যবহার করবেন না। নিরাপদে strcat () ব্যবহার করা কঠিন এবং স্ট্র্যাঙ্ক্যাট () এর এপিআই এতটা স্ব-স্বজ্ঞাত যে এটি সঠিকভাবে ব্যবহার করার জন্য প্রয়োজনীয় প্রচেষ্টাটি কোনও উপকারকে উপেক্ষা করে। আমি নিম্নলিখিত ড্রপ-ইন প্রস্তাব করছি:

#define strncat(target,source,bufsize) snprintf(target,source,"%s%s",target,source)

এটি একটি স্ট্রিকাট () ড্রপ-ইন তৈরি করতে লোভনীয়, তবে একটি ভাল ধারণা নয়:

#define strcat(target,source) snprintf(target,sizeof(target),"%s%s",target,source)

কারণ লক্ষ্যটি পয়েন্টার হতে পারে (সুতরাং আকারে () আমাদের প্রয়োজনীয় তথ্য ফেরত দেয় না)। আপনার কোডে strcat () এর উদাহরণগুলির জন্য আমার কাছে ভাল "সার্বজনীন" সমাধান নেই।

যে সমস্যাটি আমি প্রায়শই "strFunc () - সচেতন" প্রোগ্রামারদের মুখোমুখি হয়ে থাকি তা হ'ল স্ট্র্লেন () ব্যবহার করে বাফার-ওভারফ্লো থেকে রক্ষা করার চেষ্টা। বিষয়বস্তুগুলি NUL- সমাপ্ত হওয়ার গ্যারান্টিযুক্ত থাকলে এটি ঠিক আছে। অন্যথায়, স্ট্রেন () নিজেই বাফার-ওভাররন ত্রুটির কারণ হতে পারে (সাধারণত একটি বিভাগ বিধি লঙ্ঘন বা অন্য কোর-ডাম্প পরিস্থিতির দিকে নিয়ে যায়), আপনি সুরক্ষার চেষ্টা করছেন এমন "সমস্যাযুক্ত" কোড পৌঁছানোর আগে।


-2

আতোই থ্রেড নিরাপদ নয়। আমি ম্যান পৃষ্ঠা থেকে সুপারিশ অনুযায়ী পরিবর্তে স্ট্রটল ব্যবহার করি।


4
এটি মনে হয় এটি একটি নির্দিষ্ট প্রয়োগের ক্ষেত্রে প্রযোজ্য। strtol()থ্রেড-নিরাপদ হবে এবং atoi()তা হবে না এমন কোনও কারণ নেই ।
ডেভিড থর্নলি

4
স্ট্রোল ব্যবহার করার জন্য সুপারিশটির থ্রেড সুরক্ষার সাথে কোনও সম্পর্ক নেই, তবে ত্রুটি পরিচালনার সাথে। আপনি কোন ম্যান পেজ থেকে সেই তথ্যটি পেয়েছেন তা নিশ্চিত নন - আমি নীচে কোনও প্রস্তাবনা পাচ্ছি না man atoi(যদিও এটি থাকা উচিত)।
লন্ডিন 13
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.