دليل المتغيّرات

مقدمة

كما هو موضّح في صفحة نظرة عامة، يعمل رمز المضيف على إجراء استدعاءات عن بُعد لاستدعاء الإجراء عن بُعد (RPC) في المكتبة ذات وضع الحماية. ينتج عن وضع الحماية فصل الذاكرة بين العمليات، وبالتالي لا يمكن لـ "رمز المضيف" الوصول مباشرةً إلى الذاكرة في "المكتبة التي تم وضع الحماية" لها.

للتأكد من أن رمز المضيف يمكنه الوصول إلى المتغيرات وكتل الذاكرة في عملية عن بُعد ولجعل تنفيذ رمز المنطق الرئيسي أكثر بساطة، يوفر SAPI مجموعة شاملة من فئات C++. ومع ذلك، ستتمكن في كثير من الحالات أيضًا من استخدام أنواع C الأصلية.

تنشأ الحاجة إلى الأنواع الخاصة (أنواع SAPI) عند تمرير المؤشرات إلى الأنواع البسيطة وكتل الذاكرة (البنيات والمصفوفات).

على سبيل المثال، عند استدعاء دالة تستخدم مؤشرًا ما، يجب أن يتم تحويل المؤشر إلى مؤشر مقابل داخل ذاكرة "مكتبة وضع الحماية". يقدم مقتطف الرمز أدناه تمثيلاً بصريًا لهذا السيناريو. بدلاً من مصفوفة من ثلاثة أعداد صحيحة، يتم إنشاء كائن ::sapi::v::Array<int> يمكن تمريره بعد ذلك في طلب البيانات من واجهة برمجة التطبيقات لمكتبة وضع الحماية:

int arr[3] = {1, 2, 3};
sapi::v::Array<int> sarr(arr, ABSL_ARRAYSIZE(arr));

للحصول على نظرة عامة شاملة على جميع أنواع SAPI المتاحة، يُرجى مراجعة ملفات العنوان var_*.h في رمز مصدر مشروع SAPI. توفر ملفات العناوين هذه فئات وقوالب تمثل أنواعًا مختلفة من البيانات، على سبيل المثال:

  • تمثل ::sapi::v::UChar أحرفًا معروفة غير موقَّعة
  • تمثّل ::sapi::v::Array<int> صفيفًا من الأعداد الصحيحة.

أنواع SAPI

يقدم هذا القسم ثلاثة أنواع SAPI شائعة الاستخدام في رمز المضيف.

مؤشرات SAPI

إذا كانت الدالة المطلوب وضعها في وضع الحماية تتطلب تمرير مؤشر، يجب الحصول على هذا المؤشر من إحدى طرق PtrXXX() أدناه. يتم تنفيذ هذه الطرق بواسطة فئات متغيرات SAPI.

أنواع المؤشرات
::PtrNone() لا تتم مزامنة الذاكرة الأساسية بين عملية "رمز المضيف" وعملية "المكتبة ذات وضع الحماية" عند تمريرها إلى دالة واجهة برمجة تطبيقات في وضع الحماية.
::PtrBefore() لمزامنة ذاكرة العنصر الذي يشير إليه قبل إجراء استدعاء دالة واجهة برمجة التطبيقات في وضع الحماية. وهذا يعني أنّه سيتم نقل الذاكرة المحلية للمتغيّر ذي النقطة إلى عملية "المكتبة الموضوعة في وضع الحماية" قبل بدء الاستدعاء.
::PtrAfter() مزامنة ذاكرة العنصر الذي يشير إليه بعد حدوث استدعاء دالة واجهة برمجة التطبيقات في وضع الحماية. وهذا يعني أنّه سيتم نقل الذاكرة البعيدة للمتغيّر المدبّب إلى ذاكرة عملية "رمز المضيف" بعد اكتمال المكالمة.
::PtrBoth() يجمع بين وظائف ::PtrBefore() و::PtrAfter().

ويمكن العثور على وثائق مؤشرات SAPI هنا.

هيكل SAPI

تم توثيق النموذج ::sapi::v::Struct في var_struct.h. ويوفر دالة إنشاء يمكن استخدامها لإحاطة البنى الحالية. يوفر بنية SAPI جميع الطرق الموضحة في مؤشرات SAPI للحصول على كائن ::sapi::v::Ptr الذي يمكن استخدامه لاستدعاءات المكتبة الموضوعة في وضع الحماية.

يعرض مقتطف الرمز أدناه البنية التي يتم بدؤها ثم تمريرها إلى استدعاء دالة في وضع الحماية في مثال zlib:

sapi::v::Struct<sapi::zlib::z_stream> strm;
…
if (ret = api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
                             version.PtrBefore(), sizeof(sapi::zlib::z_stream));
…

في حال كانت البنية الحالية تحتوي على مؤشرات، ستشير هذه المؤشرات إلى العناوين في Sandboxee. ونتيجةً لذلك، سيكون عليك نقل بيانات Sandboxee قبل أن يصبح بإمكان رمز المضيف الوصول إليها.

صفائف SAPI

تم توثيق النموذج ::sapi::v::Array في var_array.h. ويوفر دالتَي إنشاء، إحداهما يمكن استخدامها لالتفاف صفائف العناصر الحالية والأخرى لإنشاء صفيف ديناميكيًا.

يعرض مقتطف الرمز هذا (المأخوذ من مثال المجموع) استخدام الدالة الإنشائية التي تحيط بمصفوفة لا يملكها هذا الكائن:

int arr[10];
sapi::v::Array<int> iarr(arr, ABSL_ARRAYSIZE(arr));

يعرض مقتطف الرمز هذا مثالاً على الدالة الإنشائية المستخدَمة لإنشاء صفيف بشكل ديناميكي:

sapi::v::Array<uint8_t> buffer(PNG_IMAGE_SIZE(*image.mutable_data()));

توفر مصفوفة SAPI جميع الطرق الموضحة في مؤشرات SAPI للحصول على كائن ::sapi::v::Ptr الذي يمكن استخدامه لاستدعاءات المكتبة الموضوعة في وضع الحماية.