
سلسلة أدوات Go موجّهة نحو الأمن، تركّز على قدرات Fuzzing على أحدث مستوى.
# gosentry
[](https://github.com/trailofbits/gosentry/actions/workflows/go.yml)
gosentry هو فرع (fork) من سلسلة أدوات Go تركّز على الأمان، يدمج العديد من الميزات لحملات التضمين (fuzzing) المتطورة على قواعد أكواد Go. إذا كنت تستخدم `go test -fuzz` سابقًا، فينبغي أن تستخدم gosentry كبديل.
يأتي هذا مع تحسينات متنوعة للتضمين وكاشفات أخطاء غير موجودة أصلاً في سلسلة أدوات Go. انظر TLDR; أدناه. يمكنك أيضًا قراءة المقالة المرتبطة بالمدونة [هنا](https://blog.trailofbits.com/2026/05/12/go-fuzzing-was-missing-half-the-toolkit.-we-forked-the-toolchain-to-fix-it./).
**TLDR (الميزات والخيارات)**:
- قم بتضمين مدخلات `struct` مباشرة (بدون الحاجة إلى محلل مخصص). أضف بذورًا باستخدام `f.Add(Input{N: 7, S: "hi"})` ثم `f.Fuzz(func(t *testing.T, in Input) { ... })`.
- التوقف (Panic) عند تجاوز سعة الأعداد الصحيحة واكتشاف مشاكل العمليات الحسابية
- التضمين باستخدام LibAFL لتقنيات تضمين متطورة مثل حل قيود المسار
- توليد/تحوير المدخلات من قواعد نحوية لتجنب التحويرات غير المفيدة. التحوير يولّد عملية رياضية صحيحة مثل `X + Y - Z` يمكن أن تصبح `X / U + Z - 14` بدلاً من `X + Yè - Z`
- التوقف (Panic) عند استدعاء دوال محددة (مثل مسجلات الأخطاء الحرجة) والانهيار عند استدعائها
- تركيز المُضمِّن على الأسطر المعدّلة حديثًا وعلى التغطية الجديدة لاستهداف الالتزامات (commits) الجديدة بشكل أساسي
- اكتشاف سباقات البيانات (data races) أثناء التضمين
- اكتشاف تسريبات Go أثناء التضمين
- اكتشاف التنفيذات العالقة عبر المهلات الزمنية أثناء التضمين
- توليد تقرير تغطية HTML من مجموعة حملة تضمين بأمر CLI واحد
## فهرس المحتويات
- [البناء](#build)
- [الميزة 1: التضمين المدرك للبنى (تضمين البنى كمدخلات)](#feature-1-struct-aware-fuzzing-fuzz-structs-as-inputs)
- [الميزة 2: اكتشاف مشاكل تجاوز السعة والاقتطاع للأعداد الصحيحة](#feature-2-integer-overflow-and-truncation-issues-detection)
- [الميزة 3: التوقف عند دوال محددة](#feature-3-panic-on-selected-functions)
- [الميزة 4: التضمين المتطور باستخدام LibAFL](#feature-4-libafl-state-of-the-art-fuzzing)
- [الميزة 5: التضمين الموجّه بـ Git-blame (تجريبي)](#feature-5-git-blame-oriented-fuzzing-experimental)
- [الميزة 6: اكتشاف حالات السباق وتسريبات goroutine والتعليق أثناء التضمين](#feature-6-detect-race-conditions-goroutine-leaks-and-hangs-at-fuzz-time)
- [الميزة 7: التضمين القائم على القواعد النحوية (Nautilus)](#feature-7-grammar-based-fuzzing-nautilus)
- [الميزة 8: توليد تقارير تغطية التضمين من الحملة](#feature-8-generate-go-coverage-reports-from-fuzzing-campaign)
- [الاكتشافات](#trophies)
- [الاعتمادات](#credits)
## البناء```bash
cd src && ./make.bash # Produces `../bin/go`. See `GOFLAGS` below.
```
> [!TIP]
> وثائق المساهمين: اقرأ `docs/gosentry/index.md` للحصول على خريطة الكود، وحلقة التطوير الموصى بها، ونقاط دخول CI، وسكربتات القياس.
> يستخدم هذا الفرع تطبيق Pull GitHub لفتح ودمج PRs تلقائيًا من `golang/go:master` إلى `master`، مما يضمن ألا نتخلف أبدًا عن أحدث تحديثات سلسلة أدوات Go.
## الميزة 1: الاختبار التلقائي المبني على البنى (fuzz structs كمدخلات)
#### نظرة عامة
الاختبار التلقائي الأصلي في Go (`go test -fuzz=...`) يدعم فقط مجموعة صغيرة من الأنواع العددية كوسائط للاختبار التلقائي (`[]byte`, `string`, أرقام, ...). في gosentry، يمكنك أيضًا اختبار **الأنواع المركبة** المبنية من تلك الأنواع العددية: البنى (structs)، المصفوفات، الشرائح، والمؤشرات.
هذا مفيد عندما يتلقى الكود الخاص بك مدخلات منظمة بشكل طبيعي ولا تريد بناء مُرمِّز/مُفكِّك ترميز مخصص فقط لتزويد المجموعة (corpus) وتغييرها.
انظر `test/gosentry/examples/multiargs` و `test/gosentry/examples/composite` للحصول على أمثلة.
#### مثال بسيط```go
type Input struct {
Data []byte
S string
N int
OK bool
}
func FuzzStructInput(f *testing.F) {
// Seed the initial corpus with a Go struct (gosentry feature).
f.Add(Input{Data: []byte("A"), S: "B", N: 7, OK: true})
f.Fuzz(func(t *testing.T, in Input) {
if in.OK && in.N == 1337 && in.S == "BOOMMOOB" && bytes.Equal(in.Data, []byte("A")) {
t.Fatalf("boom")
}
})
}
```
<details>
<summary><strong>كيف تعمل بذور البنى (<code>f.Add</code>) والتفزيز البنيوي (اللاصق المُصنَّع)</strong></summary>
لا يمكن للمفزز الأصلي في Go تفزيز قيمة `struct` مباشرة (فهو يعرف فقط كيفية تحوير قائمة صغيرة من الأنواع العددية). يضيف gosentry طبقة لاصقة صغيرة: عندما يستهدف المفزز أنواعًا مركّبة (مثل `Input`)، يقوم gosentry بتفزيز `[]byte` واحدة خلف الكواليس. في كل تنفيذ، يقوم **بفك ترميز** تلك البايتات إلى البنية الخاصة بك (حقلًا بحقل، وبشكل تكراري للمقاطع/المصفوفات/المؤشرات) ثم يستدعي رد اتصال `f.Fuzz` بالقيمة المفكوكة. يُستخدم نفس **الترميز** للبذور، لذا فإن `f.Add(Input{...})` يصبح إدخال مجموعة بايتات مشفّرة يمكن للمفزز إعادة استخدامها وتحويرها مثل أي بذرة أخرى.
تقوم المفززات (بما فيها LibAFL) بتحوير البايتات الخام، لذلك نريد وحدة فك ترميز يمكنها تحويل **أي** شريحة بايتات إلى قيمة بنية "ما" والاستمرار. JSON/`gob` سترفض معظم المدخلات العشوائية (أمر سيء للتغطية)، كما أنها لا تملأ الحقول غير المُصدَّرة، بينما غالبًا ما يستفيد التفزيز من كسر القيود الثابتة. هذا التنسيق المخصص صغير وسريع وحتمي ومتسامح مع البيانات التالفة.
في الكواليس، يستخدم هذا تنسيق gosentry الثنائي البسيط الخاص (ليس `gob` وليس JSON). الكود موجود في `src/testing/libafl.go`:
- الترميز: `libaflMarshalInputs` / `libaflAppendValue`
- فك الترميز: `libaflUnmarshalArgs` / `libaflDecodeValue`
قواعد الترميز (بشكل عام):
- `bool`: 1 بايت (`0` أو `1`)
- الأعداد الصحيحة: بايتات بالترتيب القليل الأهمية أولاً (`int`/`uint` حجمها 8 بايتات)
- الأعداد العشرية: بتات IEEE-754 بالترتيب القليل الأهمية أولاً (`float32` = 4 بايتات، `float64` = 8 بايتات)
- `string`: `uvarint(len)` ثم بايتات السلسلة الخام
- `[]byte`: `uvarint(len)` ثم البايتات الخام
- المقاطع الأخرى: `uvarint(len)` ثم ترميز كل عنصر
- البنى: تُرمَّز الحقول بترتيب التصريح
- المؤشرات: 1 بايت (`0` = فارغ، `1` = موجود) ثم القيمة المُشار إليها
</details>
## الميزة 2: كشف تجاوز الأعداد الصحيحة ومشاكل الاقتطاع
#### نظرة عامة
هذا العمل مستوحى من الأداة المطورة سابقًا [go-panikint](https://github.com/trailofbits/go-panikint). يضيف كشفًا للتجاوز (overflow) والتجاوز السفلي (underflow) في العمليات الحسابية على الأعداد الصحيحة، و(اختياريًا) كشفًا لاقتطاع الأنواع في تحويلات الأعداد الصحيحة. عند اكتشاف تجاوز أو اقتطاع، يُطلق panic برسالة خطأ مفصلة، تشمل نوع العملية المحدد والأنواع الصحيحة المعنية.
_العمليات الحسابية_: تتعامل مع الجمع `+` والطرح `-` والضرب `*` والقسمة `/` لكل من الأنواع الصحيحة الموقّعة وغير الموقّعة. للأعداد الموقّعة، تشمل `int8` و`int16` و`int32`. للأعداد غير الموقّعة، تشمل `uint8` و`uint16` و`uint32` و`uint64`. حالة القسمة تكشف تحديدًا حالة التجاوز `MIN_INT / -1` للأعداد الموقّعة. `int64` و`uintptr` لا يتم فحصهما في العمليات الحسابية.
_كشف اقتطاع النوع_: يكشف تحويلات الأنواع الصحيحة التي قد تسبب فقدانًا للبيانات. يشمل جميع الأنواع الصحيحة: `int8` و`int16` و`int32` و`int64` و`uint8` و`uint16` و`uint32` و`uint64`. يستبعد `uintptr` بسبب استخدامه المعتمد على المنصة. هذا معطّل افتراضيًا.
كشف التجاوز مفعّل افتراضيًا. لتعطيله، أضف `GOFLAGS='-gcflags=-overflowdetect=false'` قبل تنفيذ `./make.bash`. يمكنك أيضًا تفعيل فاحص الاقتطاع بإضافة: `-gcflags=-truncationdetect=true`
#### كيف يعمل
تقوم هذه الميزة بتعديل توليد SSA في المترجم بحيث تحصل العمليات الحسابية على الأعداد الصحيحة وتحويلات الأعداد الصحيحة على فحوصات إضافية في زمن التشغيل تستدعي بيئة التشغيل لإطلاق panic برسالة خطأ مفصلة عند اكتشاف خطأ. تُطبَّق الفحوصات باستخدام تصفية مبنية على موقع المصدر بحيث يتم تزويد كود المستخدم بالفاحصات بينما يتم تخطي ملفات المكتبة القياسية والتبعيات (ذاكرة الوحدات و`vendor/`).
يمكنك قراءة مقالة المدونة المرتبطة بهذا الموضوع [**هنا**](https://blog.trailofbits.com/2025/12/31/detect-gos-silent-arithmetic-bugs-with-go-panikint/).
#### كبت النتائج الإيجابية الكاذبة
أضف علامة على نفس سطر العملية أو السطر الذي يسبقه مباشرة لكبت تقرير محدد:
- تجاوز/تجاوز سفلي: `overflow_false_positive`
- اقتطاع: `truncation_false_positive`
مثال:```go
// overflow_false_positive
intentionalOverflow := a + b
// truncation_false_positive
x := uint8(big)
sum2 := a + b // overflow_false_positive
x2 := uint8(big) // truncation_false_positive
```
أحيانًا قد لا يعمل هذا، والسبب أن Go تقوم بتضمين الدالة (inlining). إذا لم يكن `// overflow_false_positive` كافيًا، أضف `//go:noinline` قبل توقيع الدالة الخاصة بك.
## الميزة 3: التسبب في panic عند استدعاء دوال محددة
عند فحص الأهداف باستخدام fuzzing، قد نكون مهتمين بتفعيل panic عند استدعاء دوال معينة. على سبيل المثال، قد تصدر بعض البرامج رسائل `log.error` بدلاً من التسبب في panic، على الرغم من أن هذه الحالات غالبًا ما تشير إلى حالات يريد باحثو الأمان اكتشافها أثناء fuzzing.
ومع ذلك، عادةً ما يتم التعامل مع هذه الأخطاء داخليًا (على سبيل المثال، عبر آليات إعادة المحاولة أو الإيقاف المؤقت، أو عبر طباعة الرسائل في السجلات)، مما يجعلها غير مرئية إلى حد كبير لأدوات fuzzing. الهدف من هذه الميزة هو معالجة هذه المشكلة.
#### طريقة الاستخدام
قم بتجميع gosentry، ثم استخدم الخيار `--panic-on`.```bash
./bin/go test -fuzz=FuzzHarness --use-libafl --focus-on-new-code=false --catch-races=false --catch-leaks=false --panic-on="test_go_panicon.(*Logger).Warning,test_go_panicon.(*Logger).Error"
```
المثال أعلاه سيُحدث panic عند استدعاء إما `(*Logger).Warning` أو `(*Logger).Error` (قائمة مفصولة بفواصل).
<details>
<summary><strong>كيف تعمل ميزة panic على الدوال المحددة</strong></summary>```text
┌───────────────────────────────────────────────────────────────────────────┐
│ 1) gosentry `go test` │
│ - parses + validates `-panic-on=...` against packages being built │
│ - forwards patterns to the compiler via `-panic-on-call=...` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 2) `cmd/compile` │
│ - prevents inlining of matching calls so the call stays visible │
│ - SSA pass inserts a call to `runtime.panicOnCall(...)` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 3) `runtime.panicOnCall` │
│ - panics with: "panic-on-call: func-name" │
└───────────────────────────────────────────────────────────────────────────┘
```
عمليًا، يجعل هذا أي موقع استدعاء مطابق يتصرف كتعطل/ذعر لأدوات الفزّينغ (لاحظ: يمكن احتجاز مواقع الاستدعاء الثابتة فقط).
</details>
## الميزة 4: فزّينغ متطور مع LibAFL
يقدم LibAFL أداءً *أفضل بكثير* من أداة فزّينغ Go التقليدية. عند الفزّينغ (`go test -fuzz=...`)، يستخدم gosentry [LibAFL](https://github.com/AFLplusplus/LibAFL) **افتراضيًا** (المشغل في `golibafl/`).
ملاحظة ثبات: في وضع LibAFL، يفرض gosentry `GODEBUG=updatemaxprocs=0` (تعطيل تحديثات GOMAXPROCS التلقائية في وقت التشغيل) لتجنب تعطل متقطع في CI الخاص بنظام Linux ("sync: inconsistent mutex state"). التفاصيل في `misc/gosentry/USE_LIBAFL.md`.
عند استخدام LibAFL (الوضع الافتراضي)، يجب عليك أن تختار صراحةً ما إذا كنت تريد تفعيل الجدولة المدركة لـ git أم لا: `--focus-on-new-code=true|false`. مزيد من التوثيق في [ملف Markdown هذا.](https://github.com/trailofbits/gosentry/blob/master/misc/gosentry/USE_LIBAFL.md)
يمكنك أيضًا تمرير ملف إعداد JSONC اختياري لـ LibAFL (بما في ذلك خيارات الفزّينغ القواعدي)، انظر [هنا.](https://github.com/trailofbits/gosentry/blob/master/misc/gosentry/libafl.config.jsonc)
مع `"stop_all_fuzzers_on_panic": false`، يحفظ LibAFL كل تعطل ويعيد تشغيل عميله لمواصلة الفزّينغ.```bash
./bin/go test -fuzz=FuzzHarness --focus-on-new-code=false --catch-races=false --catch-leaks=false --libafl-config=path/to/libafl.jsonc # optional --libafl-config
```
استخدم `-fuzztime=1m` لإيقاف حملة LibAFL بعد دقيقة واحدة.
توليد تقرير التغطية من مجموعة حملة LibAFL موثق في [الميزة 8](#feature-8-generate-go-coverage-reports-from-fuzzing-campaign).
التضمين القائم على القواعد (Nautilus) موثق في [الميزة 7](#feature-7-grammar-based-fuzzing-nautilus).
<details>
<summary><strong>كيف يتم ربط Go مع LibAFL معًا</strong></summary>```text
┌───────────────────────────────────────────────────────────────────────────┐
│ 1) gosentry `go test` │
│ - captures `testing.F.Fuzz(...)` callback │
│ - generates extra source file: `_libaflmain.go` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 2) Generated bridge: `_libaflmain.go` │
│ - provides libFuzzer-style C ABI entrypoints: │
│ LLVMFuzzerInitialize │
│ LLVMFuzzerTestOneInput │
│ - adapts bytes -> Go types -> calls the captured fuzz callback │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 3) `libharness.a` (static archive on disk) contains: │
│ - compiled objects for all test package (+ dependencies) │
│ - generated `_testmain.go` + `_libaflmain.go` │
│ - LLVMFuzzerInitialize │
│ - LLVMFuzzerTestOneInput │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 4) `golibafl/` (Rust + LibAFL) │
│ env: HARNESS_LIB=/path/to/libharness.a │
│ fuzz loop: mutate input -> LLVMFuzzerTestOneInput(data) -> observe │
└───────────────────────────────────────────────────────────────────────────┘
```
في وضع `--use-libafl`، يقوم gosentry ببناء `libharness.a` ويقوم مشغّل Rust `golibafl` بتشغيله داخل العملية عبر نقاط دخول libFuzzer. ملاحظة: يمكن أن يشير `HARNESS_LIB` إلى أي اسم أرشيف harness (على سبيل المثال `libharness_race.a` المستخدم من قبل `--catch-races`).
</details>
<details>
<summary><strong>كيف تعمل آلية تتبع التغطية (LibAFL + هدف Go)</strong></summary>
في وضع `--use-libafl`، يقوم gosentry بترجمة harness Go مع تفعيل آلية تتبع التغطية. يضيف هذا عدّادات صغيرة إلى الكود تتغير عند تنفيذ أجزاء مختلفة من برنامجك. عندما يبدأ harness داخل `golibafl`، يكشف وقت تشغيل Go عن هذه العدّادات إلى LibAFL. يقرأ LibAFL هذه العدّادات بعد كل إدخال لمعرفة أي كود تم تنفيذه، ويستخدم تلك التغطية لتوجيه الطفرات التالية.
</details>
##### القيود
لنتحدث عن الدافع وراء استخدام LibAFL. إن التضمين باستخدام `go test -fuzz` متخلف _بكثير_ عن أحدث تقنيات التضمين. مثال جيد على ذلك هو CMPLOG/Redqueen الخاص بـ AFL++. تسمح هذه الميزات لأدوات التضمين بحل قيود معينة. لنفترض المقتطف التالي```go
if input == "IMARANDOMSTRINGJUSTCMPLOGMEMAN" {
panic("this string is illegal")
}
```
أدوات التضمين المتطورة (SOTA) مثل AFL++ أو LibAFL كانت ستكتشف الانهيار (panic) فورًا في تلك الحالة. لكن أداة التضمين الأصلية للغة Go لن تفعل ذلك. تلك فجوة هائلة تعيق استكشاف التغطية **بكثير**.
المعيار أدناه يُظهر هذه الحدود. لاحظ أن هذه المعايير يمكن **إعادة إنتاجها** وتحسينها عبر [مستودع gosentry-bench-libafl](https://github.com/kevin-valerio/gosentry-bench-libafl/tree/main).
##### المعيار 1:
الرسم البياني أدناه يوضح تطور عدد الأسطر المغطاة أثناء التضمين (Fuzzing) لمكتبة [UUID](https://github.com/google/uuid) الخاصة بجوجل باستخدام LibAFL مقابل أداة التضمين الأصلية للغة Go.

##### المعيار 2:
الرسم البياني أدناه يوضح تطور عدد الأسطر المغطاة أثناء التضمين (Fuzzing) لمشروع [go-ethereum](https://github.com/ethereum/go-ethereum) باستخدام LibAFL مقابل أداة التضمين الأصلية للغة Go.

#### مثال
يمكنك اختباره على بعض أحزمة التضمين (fuzzing harnesses) في المسار `test/gosentry/examples/`.```bash
cd test/gosentry/examples/reverse
../../../../bin/go test -fuzz=FuzzReverse --focus-on-new-code=false --catch-races=false --catch-leaks=false
```
أوقف حملة fuzz باستخدام Ctrl+C.
##### دليل مخرجات LibAFL (هوية الحملة / إعادة استخدام corpus)
يخزّن gosentry حالة حملة LibAFL (corpus، الأعطال، إلخ) تحت جذر ذاكرة التخزين المؤقت لـ fuzz في Go (تقريبًا `$(go env GOCACHE)/fuzz`)، في دليل حتمي مشتق من **نفس الحزمة + نفس هدف fuzz** (ونفس جذر المشروع).
هذا يعني أن إيقاف (Ctrl+C) وإعادة تشغيل نفس حملة fuzz سيؤدي، افتراضيًا، إلى المتابعة من corpus `queue/` السابق لـ LibAFL.
يُطبع المسار في نهاية التشغيل:```text
libafl output dir: /full/path/to/.../fuzz/<pkg import path>/libafl/<project>/<harness>
```
ملاحظات:
- `<harness>` هو اسم هدف الـ fuzz عندما يكون `-fuzz` معرّفًا بسيطًا مثل `FuzzXxx` (أو `^FuzzXxx$`)، وإلا فإنه يكون `pattern-<hash>`.
- توليد التغطية (`--generate-coverage`) يستخدم نفس القاعدة للعثور على مجموعة `queue/` الصحيحة، لذا يجب تشغيله من نفس الحزمة مع نفس `-fuzz=...`.
## الميزة 5: التضمين الموجَّه بـ Git-blame (تجريبي)
#### نظرة عامة
التضمين الموجَّه بالتغطية ممتاز في استكشاف مسارات جديدة، لكنه يعامل جميع الأكواد المغطاة على أنها مثيرة للاهتمام بنفس القدر. عند تضمين قواعد أكواد كبيرة، قد ترغب في تحيز أداة التضمين نحو الأكواد المعدلة مؤخرًا، حيث من المرجح أن تُدخل الانحدارات والعلل. في وضع LibAFL، يمكن لـ gosentry استخدام `git blame` لتفضيل المدخلات التي تنفذ أسطرًا تغيرت مؤخرًا (مع الإبقاء على توجيه التغطية كإشارة أساسية).
يستند هذا العمل إلى عمل سابق من [LibAFL-git-aware](https://github.com/kevin-valerio/LibAFL-git-aware). جميع التفاصيل التقنية المعمقة موثقة هناك.
#### طريقة الاستخدام
فعّل الجدولة الموجَّهة بـ git باستخدام `--focus-on-new-code=true`:```bash
./bin/go test -fuzz=FuzzHarness --use-libafl --focus-on-new-code=true --catch-races=false --catch-leaks=false
```
يتطلب هذا الوضع `git` (لتشغيل `git blame`) و`go tool addr2line` لتعيين عدادات التغطية مرة أخرى إلى المصدر `file:line`.
<details>
<summary><strong>كيف يعمل fuzzing الموجَّه بـ git-blame</strong></summary>```text
┌───────────────────────────────────────────────────────────────────────────┐
│ 1) gosentry `go test -fuzz` │
│ - builds `libharness.a` (contains `go.o` + `.go.fuzzcntrs`) │
│ - runs `golibafl` with `GOLIBAFL_FOCUS_ON_NEW_CODE=1` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 2) `golibafl` generates a cached "git recency map" │
│ - maps coverage counters -> (file:line) via `go tool addr2line` │
│ - runs `git blame` to get a timestamp per line │
│ - stores timestamps in `git_recency_map.bin` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 3) LibAFL scheduler uses the recency map │
│ - coverage decides what enters the corpus │
│ - among the corpus, prioritize inputs that hit newer lines │
└───────────────────────────────────────────────────────────────────────────┘
```
</details>
<details>
<summary><strong>كيف ينشئ gosentry ملف <code>git_recency_map.bin</code></strong></summary>
`.go.fuzzcntrs` هو قسم الرابط الذي يحمل عدادات التغطية **8-بت** بنمط libFuzzer الخاصة بلغة Go (مفعّلة عبر `-gcflags=all=-d=libfuzzer`)؛ كل بايت يمثل "عدد المرات التي تم فيها الوصول إلى هذه النقطة المُجهزة". عند استخدام `--focus-on-new-code=true`، يقوم `golibafl` بإنشاء `git_recency_map.bin` عبر:
1. استخراج `go.o` من `libharness.a`.
2. قراءة حجم قسم `.go.fuzzcntrs` للحصول على عدد العدادات `N`.
3. فحص عمليات إعادة التوطين في `.text` التي تشير إلى رموز `.go.fuzzcntrs` لاستعادة العنوان لكل فهرس عداد.
4. تحويل كل عنوان إلى `file:line` باستخدام `go tool addr2line`.
5. تشغيل `git blame --line-porcelain` للحصول على `committer-time` لكل سطر.
6. كتابة `git_recency_map.bin` كـ `u64 head_time` + `u64 N` + `N * u64 timestamps` (بترتيب البايتات الأقل أهمية). الإدخالات غير المعيّنة تستخدم الطابع الزمني `0`.
</details>
<details>
<summary><strong>المعيار 1 (go-ethereum / geth): خط الأساس مقابل git-aware</strong></summary>
تم التنفيذ باستخدام `misc/gosentry/bench_focus_on_new_code_geth.sh --trials 5 --warmup 600 --timeout 200`.
</details>```text
gitaware_5: crash (7122ms)
baseline results:
trial 1: crash (107747ms)
trial 2: crash (146415ms)
trial 3: crash (37902ms)
trial 4: crash (154034ms)
trial 5: timeout (200000ms)
baseline crashes: 4/5 (timeouts=1, errors=0)
baseline median (capped to timeout): 146.415s
git-aware results:
trial 1: timeout (200000ms)
trial 2: crash (87432ms)
trial 3: crash (61733ms)
trial 4: crash (157540ms)
trial 5: crash (7122ms)
git-aware crashes: 4/5 (timeouts=1, errors=0)
git-aware median (capped to timeout): 87.432s
```
</details>
## الميزة 6: اكتشاف حالات السباق، وتسريبات الغوروتين، والتعليق (انتهاء المهلة) أثناء وقت التضمين
##### اكتشاف التعليقات المؤكدة (انتهاء مهلة LibAFL)
عند التضمين باستخدام LibAFL، يمكن أن ينتهي تنفيذ الـ harness **بمهلة** (على سبيل المثال بسبب طريق مسدود / غوروتينات عالقة في الانتظار، أو مسار بطيء للغاية).
```
---
[Read more](https://github.com/trailofbits/gosentry)