স্মৃতি সুরক্ষা আজকাল সমস্ত ক্রোধ। তবে শব্দটির অর্থ কী? এটি আপনার ভাবার চেয়ে পেরেক দেওয়া আরও শক্ত হয়ে উঠেছে। সাধারণত, লোকেরা এই শব্দটিকে এমন ভাষাগুলি উল্লেখ করতে ব্যবহার করে যা নিশ্চিত করে যে প্রোগ্রামে কোনও ব্যবহার-মুক্ত বা বাইরে বাউন্ডের মেমরি অ্যাক্সেস নেই। এটি প্রায়শই থ্রেড সুরক্ষার মতো সুরক্ষার অন্যান্য ধারণাগুলির থেকে পৃথক হিসাবে দেখা যায়, যা এমন প্রোগ্রামগুলিকে বোঝায় যেগুলি নির্দিষ্ট ধরণের সম্মতি বাগ নেই। যাইহোক, এই পোস্টে আমি যুক্তি দেব যে এই পার্থক্যটি এতটা কার্যকর নয় এবং আমরা আমাদের প্রোগ্রামগুলি যে প্রকৃত সম্পত্তিটি চাই তা হ’ল অপরিজ্ঞাত আচরণের অনুপস্থিতি।
একটি ডেটা রেসের সাথে মেমরি সুরক্ষা ভাঙা
মেমরি সুরক্ষা এবং থ্রেড সুরক্ষার মতো সূক্ষ্ম-দানাযুক্ত শ্রেণিতে সুরক্ষার বিভাজন নিয়ে আমার মূল সমস্যাটি হ’ল কোনও অর্থবহ ধারণা নেই যাতে একটি থ্রেড-অন্সাফে ভাষা স্মৃতি সুরক্ষা সরবরাহ করে। এর দ্বারা আমি কী বোঝাতে চাইছি তা দেখতে, এই প্রোগ্রামটি জিওতে লিখিত বিবেচনা করুন, যা উইকিপিডিয়া অনুসারে স্মৃতি-নিরাপদ:
package main
// Just some arbitrary interface so we can later use an interface type.
type Thing interface {
get() int
}
// Two types implementing the interface, with fields of very different types.
type Int struct {
val int
}
func (s *Int) get() int {
return s.val
}
type Ptr struct {
val *int
}
func (s *Ptr) get() int {
return *s.val
}
// A global variable of interface type, that we will swap back and
// forth between pointing to an `Int` and to a `Ptr`.
var globalVar Thing = &Int { val: 42 }
// Repeatedly invoke the interface method on the global variable.
func repeat_get() {
for {
x := globalVar
x.get()
}
}
// Repeatedly change the dynamic type of the global variable.
func repeat_swap() {
var myval = 0
for {
globalVar = &Ptr { val: &myval }
globalVar = &Int { val: 42 }
}
}
func main() {
go repeat_get()
repeat_swap()
}
আপনি যদি এই প্রোগ্রামটি চালনা করেন (উদাহরণস্বরূপ খেলার মাঠে যান), এটি খুব দ্রুত ক্রাশ হবে:
panic: runtime error: invalid memory address or nil pointer dereference
(signal SIGSEGV: segmentation violation code=0x1 addr=0x2a pc=0x468863)
নোট করুন যে সেগফল্ট যে ঠিকানাটি ঘটেছে তা হ’ল 0x2a
42 এর হেক্স উপস্থাপনা এখানে কি হচ্ছে?
এই উদাহরণটি শোষণ করে যা ইন্টারফেস ধরণের মান সঞ্চয় করে Thing
ডেটাতে একটি পয়েন্টার জোড়া এবং ভিটেবলের একটি পয়েন্টার হিসাবে। প্রতিবার repeat_swap
একটি নতুন মান সঞ্চয় globalVar
এই দুটি পয়েন্টার আপডেট করতে এটি কেবল দুটি পৃথক স্টোর করে। মধ্যে repeat_get
আমরা যখন পড়ি তখন একটি ছোট সুযোগ আছে globalVar
মধ্যে এই দুটি স্টোর, আমরা একটি পয়েন্টারের মিশ্রণ পাই Int
একটি জন্য vtabl সঙ্গে Ptr
। যখন এটি ঘটে, আমরা চালাব Ptr
সংস্করণ get
যা নির্জন হবে Int
‘এস val
একটি পয়েন্টার হিসাবে ক্ষেত্র – এবং তাই প্রোগ্রামটি ঠিকানা 42 এবং ক্র্যাশগুলি অ্যাক্সেস করে।
কেউ জিও এর স্লাইসগুলি ব্যবহার করে অনুরূপ উদাহরণ তৈরি করতে পারে, যেখানে স্লাইসের ডেটা পয়েন্টার, দৈর্ঘ্য এবং ক্ষমতা পৃথক কথায় সংরক্ষণ করা হয় এবং একটি অর্ধ-আপডেট হওয়া মান পড়া একটি বহিরাগত-বাউন্ডের অ্যাক্সেসের দিকে পরিচালিত করতে পারে।
অন্যান্য ভাষা সম্পর্কে কি?
এই মুহুর্তে আপনি ভাবছেন, এটি কি অনেক ভাষায় সমস্যা নয়? জাভাও কি ডেটা রেসের অনুমতি দেয় না? এবং হ্যাঁ, জাভা ডেটা রেসের অনুমতি দেয়, তবে জাভা বিকাশকারীরা ডেটা রেস সহ প্রোগ্রামগুলিও সম্পূর্ণরূপে সংজ্ঞায়িত রয়েছে তা নিশ্চিত করার জন্য প্রচুর প্রচেষ্টা ব্যয় করেছিল। এমনকি তারা বিকাশ প্রথম শিল্পে মোতায়েন করা সম্মিলিত মেমরি মডেল এই উদ্দেশ্যে, সি ++ 11 মেমরি মডেলের অনেক বছর আগে। এই সমস্ত কাজের ফলাফলটি হ’ল একযোগে জাভা প্রোগ্রামে আপনি নির্দিষ্ট ভেরিয়েবলের জন্য অপ্রত্যাশিত পুরানো মানগুলি দেখতে পাবেন, যেমন একটি নাল পয়েন্টার যেখানে আপনি প্রত্যাশা করেছিলেন যে রেফারেন্সটি সঠিকভাবে আরম্ভ করা হবে, তবে আপনি করবেন কখনও না ঠিকানায় ভাষাটি ভেঙে ফেলতে সক্ষম হোন 0x2a
। সেই অর্থে, সমস্ত জাভা প্রোগ্রামগুলি থ্রেড-নিরাপদ।
সাধারণত, সম্মিলনটি বেসিক আক্রমণকারীদের ভঙ্গ না করে তা নিশ্চিত করার জন্য একটি ভাষা অনুসরণ করতে পারে এমন দুটি বিকল্প রয়েছে:
- নিশ্চিত করুন যে স্বেচ্ছাসেবী সমবর্তী প্রোগ্রামগুলি আসলে কিছু অর্থে “যুক্তিসঙ্গতভাবে” আচরণ করে। এটি একটি উল্লেখযোগ্য ব্যয়ে আসে, ভাষাটিকে সীমাবদ্ধ করে যে বহু-শব্দের মানগুলির ধারাবাহিকতা ধরে না এবং সংকলকটি সম্পাদন করতে পারে এমন অপ্টিমাইজেশনগুলি সীমাবদ্ধ করে না। জাভা থেকে সি#, ওকামল, জাভাস্ক্রিপ্ট এবং ওয়েবসেম্বলি পর্যন্ত বেশিরভাগ ভাষাগুলি এই রুটটি গ্রহণ করে।
- বেশিরভাগ অ্যাক্সেসগুলিতে ডেটা রেসকে পুরোপুরি বাতিল করার জন্য একটি শক্তিশালী পর্যাপ্ত টাইপ সিস্টেম রয়েছে এবং মেমরি অ্যাক্সেসের একটি ছোট উপসেটের জন্য নিরাপদে দৌড়গুলির সাথে নিরাপদে ডিল করার ব্যয়টি প্রদান করে। এটিই সেই পদ্ধতির যা মরিচা প্রথমে অনুশীলনে নিয়ে আসে এবং সেই সুইফট এখন তাদের সাথেও গ্রহণ করছে “কঠোর সম্মতি”।
দুর্ভাগ্যক্রমে যান, এগুলির কোনওটিই বেছে নেওয়া বেছে নিয়েছে। এর অর্থ এটি কঠোরভাবে বলতে গেলে, কোনও মেমরি নিরাপদ ভাষা নয়: ভাষা সবচেয়ে ভাল প্রতিশ্রুতি দিতে পারে যদি একটি প্রোগ্রামে কোনও ডেটা রেস নেই (বা আরও সুনির্দিষ্টভাবে, ইন্টারফেস, স্লাইস এবং মানচিত্রের মতো সমস্যাযুক্ত মানগুলিতে কোনও ডেটা রেস নেই), তবে এর স্মৃতি অ্যাক্সেসগুলি কখনই ভুল হতে পারে না। এখন, ন্যায়সঙ্গত হওয়ার জন্য, গো ডেটা রেসগুলি সনাক্ত করতে বাইরে-বক্স টুলিংয়ের সাথে আসে, যা আমার উদাহরণে দ্রুত সমস্যাটি খুঁজে পায়। যাইহোক, একটি বাস্তব প্রোগ্রামে, এর অর্থ আপনাকে আশা করতে হবে যে আপনার পরীক্ষার স্যুটটি আপনার প্রোগ্রামটি অনুশীলনে যে সমস্ত পরিস্থিতিগুলির মুখোমুখি হতে পারে তা কভার করে, যা হুবহু একটি শক্তিশালী টাইপ সিস্টেম এবং স্ট্যাটিক সুরক্ষা গ্যারান্টিগুলি এড়ানোর উদ্দেশ্যে করা ইস্যুটির ধরণের। সুতরাং এটি অবাক হওয়ার মতো নয় ডেটা রেস জিওতে একটি বিশাল সমস্যা।
ভাষাটিকে সহজ রাখার লক্ষ্যে আমি জিওর পছন্দকে ইঞ্জিনিয়ারিং ট্রেড অফ হিসাবে গ্রহণ করতে পারি। যাইহোক, প্রকৃতপক্ষে ভাষার মতো একই বালতিতে যেতে করল ডেটা রেসের সাথে সমস্যা সমাধানের প্রচেষ্টার মধ্য দিয়ে যান ভাষার সুরক্ষা প্রতিশ্রুতিগুলি ভুলভাবে উপস্থাপন করে। এমনকি অভিজ্ঞ জিও প্রোগ্রামাররা সর্বদা বুঝতে পারে না যে আপনি কোনও অনিরাপদ অপারেশন ব্যবহার না করে বা কোনও সংকলক বা ভাষার বাগগুলি শোষণ না করে মেমরি সুরক্ষা ভাঙতে পারেন। গো একটি ভাষা ডিজাইন করা একযোগে প্রোগ্রামিংয়ের জন্য, তাই লোকেরা এই ধরণের পদক্ষেপের আশা করে না। আমি মনে করি এটি একটি সমস্যাযুক্ত অন্ধ জায়গা।
দ্য মেমরি মডেল ডকুমেন্টেশন যান এই বিষয়টি সম্পর্কে ঠিক তেমনই নয়: “অনানুষ্ঠানিক ওভারভিউ” জোর দেয় যে “বেশিরভাগ দৌড়ের সীমিত সংখ্যক ফলাফল রয়েছে” এবং মন্তব্যগুলি যে “সি এবং সি ++ এর বিপরীতে নয়, যেখানে একটি জাতি সহ যে কোনও প্রোগ্রামের অর্থ সম্পূর্ণরূপে অপরিজ্ঞাত”। আপনি বলতে পারেন যে এখানে “সর্বাধিক” ব্যবহারটি পূর্বাভাস করছে, তবে এই বিভাগটি এমন কোনও ক্ষেত্রে তালিকাভুক্ত করে না যেখানে ফলাফলের সংখ্যা সীমাহীন, তাই এটি মিস করা সহজ। এমনকি তারা দাবি করতে এতদূর এগিয়ে যায় যে জিও “আরও জাভা বা জাভাস্ক্রিপ্টের মতো”, যা আমি মনে করি যে এই ভাষাগুলি তাদের যে থ্রেড সুরক্ষা অর্জন করতে গিয়েছিল তার দৈর্ঘ্য অনুসারে বরং অন্যায়। শুধুমাত্র একটি পরবর্তী উপধারা স্পষ্টভাবে সত্য যে এটি স্বীকার কিছু গো দৌড় কর সম্পূর্ণরূপে অপরিজ্ঞাত আচরণ করুন (যা জাভা বা জাভাস্ক্রিপ্টের বিপরীতে)।
উপসংহার
আমি যুক্তি দিয়ে বলব যে মেমরি সুরক্ষা সম্পর্কে কথা বলার সময় প্রকৃত সম্পত্তির লোকেরা যত্ন করে প্রোগ্রামটি ভাষা ভাঙতে পারে না। এই সমস্ত মেমরি সুরক্ষা লঙ্ঘনের কারণে সুরক্ষা দুর্বলতা এমন ক্ষেত্রে যেখানে কোডটি এমন কিছু করেছে যা ভাষার স্পেসিফিকেশনে এমনকি সম্ভব নয়, যেমন কিছু ব্যবহারকারী-সরবরাহিত অ্যারেতে ঝাঁপ দেওয়া এবং এটি সমাবেশ কোড হিসাবে সম্পাদন করা। সাধারণ শব্দটি আমরা এমন একটি প্রোগ্রামের জন্য ব্যবহার করি যা এর মতো ভাষা ভেঙে দেয় অপরিজ্ঞাত আচরণ। আপনার প্রোগ্রামটির যে মুহুর্তে ইউবি রয়েছে, সমস্ত বেট বন্ধ রয়েছে; আক্রমণকারী তখন এই ইউবি ঠিক কীভাবে প্রকাশ করে এবং তাদের সুবিধার্থে এটি ব্যবহার করে তা নিয়ন্ত্রণ করতে পারে কিনা তা বেশিরভাগই বাস্তবায়নের বিশদ।
আমার দৃষ্টিতে, “নিরাপদ” ভাষাগুলিকে বিভক্ত করার একটি উজ্জ্বল রেখা রয়েছে যেখানে প্রোগ্রামগুলি অপরিবর্তিত আচরণ করতে পারে না এবং যেখানে তারা পারে সেখানে “অনিরাপদ” ভাষা থাকতে পারে না। এমন কোনও অর্থবহ ধারণা নেই যার মধ্যে এটি আরও মেমরি সুরক্ষা, থ্রেড সুরক্ষা, টাইপ সুরক্ষা এবং কী নয় – এটি কোনও বিষয় নয় কেন আপনার প্রোগ্রামটিতে ইউবি রয়েছে, কী গুরুত্বপূর্ণ তা হ’ল ইউবি সহ একটি প্রোগ্রাম ভাষার প্রাথমিক বিমূর্ততাগুলি অস্বীকার করে এবং এটি দুর্বলতার জন্য একটি নিখুঁত প্রজনন ক্ষেত্র।
বাস্তবে, অবশ্যই, সুরক্ষা বাইনারি নয়, এটি একটি বর্ণালী, এবং সেই বর্ণালীতে সি-এর চেয়ে সাধারণ নিরাপদ ভাষার আরও অনেক কাছাকাছি, এটি প্রশংসনীয় যে ডেটা রেসের দ্বারা সৃষ্ট ইউবি সরাসরি আউট-অফ-বন্ড বা ব্যবহার-মুক্ত অ্যাক্সেসের কারণে ইউবি-র তুলনায় আক্রমণকারীদের পক্ষে কম কার্যকর। তবে একই সাথে আমি মনে করি যে কোন সুরক্ষা কোনও ভাষা নির্ভরযোগ্যভাবে সরবরাহ করে এবং যেখানে বাণিজ্য-বন্ধগুলির অস্পষ্ট অঞ্চলটি শুরু হয় তা বোঝা গুরুত্বপূর্ণ। আমি ব্যবসায় আছি প্রমাণ করা ভাষার সুরক্ষা দাবি এবং যেতে যাওয়ার জন্য, আসলে খুব বেশি কিছু প্রমাণ করতে পারে না। আমি আশা করি এই পোস্টটি আপনাকে বিভিন্ন ভাষাগুলি যে পছন্দগুলি করেছে তার কিছু অ-তুচ্ছ পরিণতি আরও ভালভাবে বুঝতে সহায়তা করে। 🙂