Forwarded from خبرنامهٔ امیرکبیر
بر اساس گزارش اختصاصی رسیده به #خبرنامه_امیرکبیر، عرفان عربی، دانشجوی رشته مهندسی کامپیوتر دانشگاه آزاد بیرجند و از فعالان آزادی اینترنت، به ۵ سال حبس محکوم و این حکم روز جاری در دادگاه انقلاب به صورت شفاهی به وی ابلاغ شد. دادگاه انقلاب، آقای عربی را به اتهاماتی مانند «اجتماع و تبانی» و «تبلیغ علیه نظام» به ۸ سال حبس محکوم کرده که ۵ سال از آن قابل اجرا است. دادگاه همچنین از ابلاغ کتبی حکم خودداری کرده و جزئیات محکومیت تنها به شکل شفاهی به این دانشجو ابلاغ شده است.
عرفان عربی، ۲۰ ساله، دانشجوی کامپیوتر دانشگاه آزاد بیرجند و عضو تیم توسعهٔ سیستمعامل پارچ لینوکس، بهمن ماه سال گذشته پس از احضار توسط وزارت اطلاعات جمهوری اسلامی و ضبط دستگاههای الکترونیکیاش، به اتهاماتی مانند «تبلیغ علیه نظام» و «اجتماع و تبانی برای اقدام علیه امنیت ملی» بازداشت و اواخر فروردین امسال، پس از حدود سه ماه از زندان آزاد شد.
#عرفان_عربی
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9
HICTE Blog
#سی 🚁 Hicte Blog | (smm)
وضعیت کد بالا:
Final Results
30%
Safe 🎉
30%
Overflow 💥
14%
Two overflows 😱
11%
Three overflows 💀
16%
Compiler error 👻
👍3
#سی
تبدیلهای حسابی معمول و ارتقای اعداد صحیح
[قسمت اول]
وقتی دو عملوند از انواع مختلف تو یه عبارت شرکت میکنن، کامپایلر اونها رو به یه نوع مشترک تبدیل میکنه [قبل از اینکه عملیات واقعی انجام بشه]. این قرارداد تو استاندارد C با عنوان تبدیلهای حسابی معمول (Usual Arithmetic Conversions یا به اختصار UAC) شناخته میشه.
پردازندههای مدرن دستورالعملهای جداگانهای برای انواع مختلف داده دارن. دستور جمع اعداد صحیح با دستور جمع اعداد اعشاری کاملاً متفاوت هست. وقتی شما مینویسین:
پردازنده نمیتونه مستقیماً یه
قانون راهنمای این تبدیل ساده هست:
همیشه به سمت نوعی که اطلاعات بیشتری رو حفظ میکنه حرکت کن.
انواع اعشاری اولویت بالاتری از انواع صحیح دارن. توی لیست زیر به ترتیب اولویت تبدیل از بالا به پایین میشه:
این تبدیلها برای:
۱. عملگرهای حسابی
۲. عملگرهای رابطه و برابری
۳. عملگرهای بیتی
۴. عملگر سه تایی (برای عملوندهای دوم و سوم)
توسط کامپایلر اعمال میشن.
🚁 Hicte Blog | (smm)
تبدیلهای حسابی معمول و ارتقای اعداد صحیح
یکی از رفتارهای زبان C که مسئول بسیاری از باگها هست اگه درست درک نشه!
[قسمت اول]
وقتی دو عملوند از انواع مختلف تو یه عبارت شرکت میکنن، کامپایلر اونها رو به یه نوع مشترک تبدیل میکنه [قبل از اینکه عملیات واقعی انجام بشه]. این قرارداد تو استاندارد C با عنوان تبدیلهای حسابی معمول (Usual Arithmetic Conversions یا به اختصار UAC) شناخته میشه.
پردازندههای مدرن دستورالعملهای جداگانهای برای انواع مختلف داده دارن. دستور جمع اعداد صحیح با دستور جمع اعداد اعشاری کاملاً متفاوت هست. وقتی شما مینویسین:
int a = 5;
double b = 2.5;
double result = a + b;
پردازنده نمیتونه مستقیماً یه
int و یه double رو با هم جمع بزنه چون ساختار باینری اونها کاملاً متفاوت هست. کامپایلر باید قبل از انجام عملیات، هر دو عملوند رو به یه نوع مشترک تبدیل کنه.قانون راهنمای این تبدیل ساده هست:
همیشه به سمت نوعی که اطلاعات بیشتری رو حفظ میکنه حرکت کن.
انواع اعشاری اولویت بالاتری از انواع صحیح دارن. توی لیست زیر به ترتیب اولویت تبدیل از بالا به پایین میشه:
long double
double
float
long long
long
int
این تبدیلها برای:
۱. عملگرهای حسابی
* / % + -۲. عملگرهای رابطه و برابری
< <= > >= == !=۳. عملگرهای بیتی
& | ^۴. عملگر سه تایی (برای عملوندهای دوم و سوم)
?:توسط کامپایلر اعمال میشن.
🚁 Hicte Blog | (smm)
1👍6❤1
#سی
تبدیلهای حسابی معمول و ارتقای اعداد صحیح
[قسمت دوم] [لینک به قسمت اول]
ارتقای اعداد صحیح (Integer Promotion):
هر نوع دادهای که جایگاه پایینتری از
پردازندههای مدرن برای کار با مقادیر
ارتقا روی هر عملوند به صورت مجزا اتفاق میافته. حتی یه عبارت ساده مثل
بر خلاف تبدیلهای حسابی معمول، ارتقای اعداد صحیح تو همهی عملگرها اتفاق میفته حتی عملگرهایی مثل
استثناها عملگرهای
🚁 Hicte Blog | (smm)
تبدیلهای حسابی معمول و ارتقای اعداد صحیح
[قسمت دوم] [لینک به قسمت اول]
قبل از اینکه UAC بررسی بشه، یه مرحلهی مقدماتی وجود داره؛ ارتقای اعداد صحیح.
ارتقای اعداد صحیح (Integer Promotion):
هر نوع دادهای که جایگاه پایینتری از
int داشته باشه [یعنی _Bool و char و short] به طور خودکار به int ارتقا پیدا میکنه، حتی اگه هیچ متغیری از نوع int تو عبارت وجود نداشته باشه.پردازندههای مدرن برای کار با مقادیر
int بهینه شدن. بنابراین استاندارد C تعیین کرد که همه محاسبات حداقل در سطح int انجام بشن.ارتقا روی هر عملوند به صورت مجزا اتفاق میافته. حتی یه عبارت ساده مثل
c + c که فقط یه char داره، نتیجهاش int هست.بر خلاف تبدیلهای حسابی معمول، ارتقای اعداد صحیح تو همهی عملگرها اتفاق میفته حتی عملگرهایی مثل
~ که فقط یه عملوند دارن.استثناها عملگرهای
++، --، sizeof و عملگر انتساب یا همون = هستن که براشون ارتقای اعداد صحیح رخ نمیده. چون sizeof که کلا با مقدار عملوندش کاری نداره و اندازهی نوع متغیر رو محاسبه میکنه، ++ و -- هم مستقیما روی همون متغیر مینویسن، عملگر انتساب (=) هم منطقا نباید به نوع عملوند سمت چپش دست بزنه پس کلا کاری به این موضوع نداره.🚁 Hicte Blog | (smm)
👍4
#سی
تبدیلهای حسابی معمول و ارتقای اعداد صحیح
[قسمت سوم] [لینک به قسمت دوم]
ارتقای اعداد صحیح، قواعد signed و unsigned:
انواع با رتبهی پایینتر از
تنها در صورتی که نوع ما بدون علامت باشه و تمام مقادیر ممکن اون نوع توی
اگه کد بالا رو برای یه سیستم ۱۶ بیتی کامپایل کنیم موقع اجرای دستورالعمل جمع متغیر
روی سیستمهای ۱۶ بیتی نوع
اما رو سیستمهای دسکتاپ امروزی چنین اتفاقی نمیفته و
خب حالا درک نکردن ارتقای اعداد صحیح چه باگی مثلا میتونه بوجود بیاره؟
بیاین رو یه مثال ساده صحبت کنیم:
تو کد بالا متغیر
0000 0001
یه بایت که هفت بیت صفر داره و آخرین بیتش یک هست. معادل عدد یک میشه. [اعداد رو توی کد مبنای ۱۶ نوشتم تا باینریش رو بشه بصورت ذهنی راحتتر حساب کرد. هر چهار بیت رو میشه با یه رقم هگزادسیمال نشون داد.]
عملگر
خب پس ما انتظار داریم که نتیجهی
1111 1110
باشه که تو مبنای ۱۶ میشه FE اما اگه کد رو اجرا کنین میبینین که نتیجه FFFFFFFE هست! یعنی:
1111 1111, 1111 1111, 1111 1111, 1111 1110
چهار بایت که یه بایتش نتیجه مورد انتظار بود و سه بایت اضافی هستن.
خب این سه بایت (یا ۲۴ بیت) که اولش چسبیدن از کجا اومدن؟
قبل از اینکه عملگر مکمل بیتی (~) اعمال بشه بخاطر قانون ارتقای اعداد صحیح متغیر
0000 0000, 0000 0000, 0000 0000, 0000 0001
که عملگر
وقتی یه نوع کوچیکتر به نوع بزرگتر تبدیل میشه اگه مقداری که توی نوع کوچیکتر هست عددی مثبت باشه، بایتهایی که سمت چپش اضافه میشن با 0 پر میشن که بهش zero extension میگن. اگه مقدارش عددی منفی باشه بایتهایی که اضافه میشن با 1 پر میشن که بهش sign extension میگن.
حالا چیکار کنیم از شر اون سه بایت اضافی خلاص شیم؟ یه راهش اینه که مقداری که عملگر
اگه یکم نکته سنج باشین شاید بپرسین خب توی عملگر
اگه متغیرمون
از طرفی تو سمت راست
یه نکته داخل پرانتز هم هست که بخاطر محدودیت کاراکتر تلگرام توی کامنت مینویسمش.
🚁 Hicte Blog | (smm)
تبدیلهای حسابی معمول و ارتقای اعداد صحیح
[قسمت سوم] [لینک به قسمت دوم]
ارتقای اعداد صحیح، قواعد signed و unsigned:
انواع با رتبهی پایینتر از
int موقع ارتقا همیشه به int تبدیل میشن فارغ از اینکه باعلامت (signed) باشن یا بدون علامت (unsigned) اما با یه استثنا!تنها در صورتی که نوع ما بدون علامت باشه و تمام مقادیر ممکن اون نوع توی
int جا نشه، به unsigned int ارتقا پیدا میکنه.unsigned short var = 100;
var = var + 1;
اگه کد بالا رو برای یه سیستم ۱۶ بیتی کامپایل کنیم موقع اجرای دستورالعمل جمع متغیر
var که unsigned short هست به unsigned int ارتقا پیدا میکنه. روی سیستمهای ۱۶ بیتی نوع
int و نوع short هر دو ۱۶ بیت پهنا دارن در نتیجه USHRT_MAX برابر با UINT_MAX و بزرگتر از INT_MAX هست پس اینجا تمام مقادیر ممکن که توی unsigned short جا میشن توی int جا نمیشن و به unsigned int نیاز داریم.اما رو سیستمهای دسکتاپ امروزی چنین اتفاقی نمیفته و
int خیلی بزرگتر از unsigned short هست.خب حالا درک نکردن ارتقای اعداد صحیح چه باگی مثلا میتونه بوجود بیاره؟
بیاین رو یه مثال ساده صحبت کنیم:
#include <stdio.h>
int main() {
unsigned char a = 0x01;
if (~a == 0xFE) {
printf("Bits flipped correctly\n");
} else {
printf("BUG!\n");
printf("~a = 0x%X\n", ~a);
}
return 0;
}
تو کد بالا متغیر
a مقدار 0x01 رو داره [برای نوشتن اعداد مبنای ۱۶ توی سی از پیشوند 0x استفاده میکنیم.] که الگوی باینری اون برای char که یه بایت هست میشه:0000 0001
یه بایت که هفت بیت صفر داره و آخرین بیتش یک هست. معادل عدد یک میشه. [اعداد رو توی کد مبنای ۱۶ نوشتم تا باینریش رو بشه بصورت ذهنی راحتتر حساب کرد. هر چهار بیت رو میشه با یه رقم هگزادسیمال نشون داد.]
عملگر
~ کارش اینه که تو حالت باینری مقداری که تو متغیر هست همهی صفرها رو به یک و همهی یکها رو به صفر تبدیل کنه و نتیجه رو برگردونه.خب پس ما انتظار داریم که نتیجهی
~a بصورت1111 1110
باشه که تو مبنای ۱۶ میشه FE اما اگه کد رو اجرا کنین میبینین که نتیجه FFFFFFFE هست! یعنی:
1111 1111, 1111 1111, 1111 1111, 1111 1110
چهار بایت که یه بایتش نتیجه مورد انتظار بود و سه بایت اضافی هستن.
خب این سه بایت (یا ۲۴ بیت) که اولش چسبیدن از کجا اومدن؟
قبل از اینکه عملگر مکمل بیتی (~) اعمال بشه بخاطر قانون ارتقای اعداد صحیح متغیر
a از unsigned char به int ارتقا پیدا میکنه. یعنی از یه نوع یک بایتی به یه نوع چهار بایتی تبدیل میشه و سه بایت که با صفر پر شدن به سمت چپش اضافه میشه. پس a میشه:0000 0000, 0000 0000, 0000 0000, 0000 0001
که عملگر
~ میاد صفرها و یکها رو برعکس میکنه و نتیجهی که گفته شد ایجاد میشه و این باگ شکل میگیره.وقتی یه نوع کوچیکتر به نوع بزرگتر تبدیل میشه اگه مقداری که توی نوع کوچیکتر هست عددی مثبت باشه، بایتهایی که سمت چپش اضافه میشن با 0 پر میشن که بهش zero extension میگن. اگه مقدارش عددی منفی باشه بایتهایی که اضافه میشن با 1 پر میشن که بهش sign extension میگن.
حالا چیکار کنیم از شر اون سه بایت اضافی خلاص شیم؟ یه راهش اینه که مقداری که عملگر
~ برگردونده رو دوباره به unsigned char تبدیل کنیم تا سه بایت ازش کوتاه بشه.if ((unsigned char)~a == 0xFE)
اگه یکم نکته سنج باشین شاید بپرسین خب توی عملگر
== هم ارتقای اعداد صحیح رخ میده پس دوباره سه بایت به مقدارمون اضافه میشه! خب همونطور که گفتم وقتی عددمون مثبت باشه پشتش فقط صفر اضافه میشه و حالا که کار عملگر ~ تموم شده صفرها صفر میمونن و تاثیری نمیذارن.اگه متغیرمون
signed char بود اونوقت این راه حل ناقص بود. چون 0xFE یه عدد منفی (-۲) توی نوع یک بایتی char محسوب میشد. [توی انواع با علامت اگه اولین بیت از سمت چپ یک باشه اون یه عدد منفی هست نیاز نیست کل عدد رو حساب کنین.]از طرفی تو سمت راست
0xFE خالی رو داریم که توی سی بصورت پیشفرض نوع int در نظر گرفته میشه و تبدیلی براش اتفاق نمیفته. [از اول معادل 0x000000FE هست.]signed char a = 0x01;
if ((signed char)~a == 0xFE) //False
1. Integer promotion:اینجا بهتره هر دو طرف
0x01 -> 0x00000001
2. Bitwise NOT:
0x00000001 -> 0xFFFFFFFE
3. Cast to signed char:
0xFFFFFFFE -> 0xFE
4. Integer promotion:
0xFE -> 0xFFFFFFFE
Comparison:
0xFFFFFFFE == 0x000000FE
== از یه نوع استفاده کنیم تا وقتی تبدیلی رخ میده برای هر دو سمت به یه شکل تغییرات ایجاد بشن.signed char a = 0x01, b = 0xFE;
if ((signed char)~a == b) // True
یه نکته داخل پرانتز هم هست که بخاطر محدودیت کاراکتر تلگرام توی کامنت مینویسمش.
🚁 Hicte Blog | (smm)
❤4🔥3👍1
#خبر
تعداد زیادی از پکیجهایی که تو مخزن AUR بودن آلوده شدن.
هکرا رفتن سراغ پکیجهایی که از قبل تو AUR قرار داشتن اما رها شده بودن و طی فرایند رسمی انتقال، مالکیت پکیج رو بر عهده گرفتن.
لیست پکیجهای آلوده رو میتونین اینجا ببینین:
https://md.archlinux.org/s/SxbqukK6IA
[این لیست نهایی نیست و همچنان در حال بروزرسانی هست.]
برای اینکه ببینین پکیجی از لیست بالا رو سیستمتون نصب بوده یا نه میتونین از این اسکریپت که سهراب نوشته استفاده کنین:
ظاهرا این حمله ۹ ژوئن شروع شد و ۱۱ ژوئن تیم آرچ دست کرد توی AUR و حسابهای مخرب رو مسدود کرد.
واسه اطلاعات بیشتر این دوتا پست رو بخونین:
https://blog.parchlinux.com/fa/aur-compromised/
https://www.privacyguides.org/news/2026/06/12/around-1-500-aur-packages-compromised-with-rootkit-like-malware/
🚁 Hicte Blog | (smm)
تعداد زیادی از پکیجهایی که تو مخزن AUR بودن آلوده شدن.
هکرا رفتن سراغ پکیجهایی که از قبل تو AUR قرار داشتن اما رها شده بودن و طی فرایند رسمی انتقال، مالکیت پکیج رو بر عهده گرفتن.
لیست پکیجهای آلوده رو میتونین اینجا ببینین:
https://md.archlinux.org/s/SxbqukK6IA
[این لیست نهایی نیست و همچنان در حال بروزرسانی هست.]
برای اینکه ببینین پکیجی از لیست بالا رو سیستمتون نصب بوده یا نه میتونین از این اسکریپت که سهراب نوشته استفاده کنین:
#!/usr/bin/env bash
LIST_URL="https://md.archlinux.org/s/SxbqukK6IA"
echo "Fetching infected package list..."
raw=$(curl -fsSL "$LIST_URL") || { echo "ERROR: failed to fetch list"; exit 1; }
mapfile -t INFECTED_PKGS < <(
echo "$raw" \
| sed 's/<[^>]*>//g' \
| grep -E '^[a-z0-9][a-z0-9_.+\-]*[a-z0-9]$' \
| sort -u
)
count=${#INFECTED_PKGS[@]}
if [[ $count -eq 0 ]]; then
echo "ERROR: parsed 0 packages, something went wrong"
exit 1
fi
echo "Checking $count known infected packages..."
mapfile -t found < <(comm -12 <(pacman -Qmq | sort) <(printf "%s\n" "${INFECTED_PKGS[@]}" | sort))
if [[ ${#found[@]} -eq 0 ]]; then
echo "Clean: no infected packages found."
else
echo "WARNING: ${#found[@]} infected package(s) found:"
for pkg in "${found[@]}"; do
echo " - $pkg"
done
fi
ظاهرا این حمله ۹ ژوئن شروع شد و ۱۱ ژوئن تیم آرچ دست کرد توی AUR و حسابهای مخرب رو مسدود کرد.
واسه اطلاعات بیشتر این دوتا پست رو بخونین:
https://blog.parchlinux.com/fa/aur-compromised/
https://www.privacyguides.org/news/2026/06/12/around-1-500-aur-packages-compromised-with-rootkit-like-malware/
🚁 Hicte Blog | (smm)
👍3❤2🙏1
#سی
تبدیلهای حسابی معمول و ارتقای اعداد صحیح
[قسمت آخر] [لینک به قسمت سوم]
تبدیلهای حسابی معمول، قواعد signed و unsigned:
تو قسمت اول در مورد اولویت بندی انواع استاندارد موقع UAC صحبت کردیم.
حالا اگه تو عبارتی یه نوع باعلامت و نوع دیگه بدون علامت باشه اولویتها چطور تعیین میشه؟
وقتی یه عملوند signed و اون یکی unsigned باشه، قانون کلی اینه:
بیاین یه مثال ازش ببینیم:
تو عبارت
اگه نوع int چهار بایتی باشه نمایش دودویی -1 میشه:
1111 1111 1111 1111 1111 1111 1111 1111
حالا اگه همین بیتها به عنوان نوع unsigned int بخوان تفسیر بشن نمایش دهندهی عدد 4,294,967,295 هستن!
خلاصه حواستون باشه.
قبل شروع این صحبتا یه کدی تو چنل گذاشته بودم با یه نظرسنجی که میتونین از اینجا ببینین:
https://t.me/HicteBlog/1402
خب در مورد این کد ما توی خط ۶ و خط ۷ اورفلو داریم!
وقتی عبارت INT_MAX + 3 اجرا میشه، دو سمت عملگر + هر دو از نوع int هستن پس عملگر + محاسبات رو تو فضای int انجام میده و نتیجهی نهایی رو بصورت int برمیگردونه بدون اینکه ارتقایی رخ بده.
طبیعتا وقتی 3 رو به ماکسیمم مقداری که توی نوع int میتونه ذخیره بشه اضافه کنیم دیگه قابلیت این رو نداره که تو همون نوع int جا بگیره و اورفلو رخ میده.
شاید بعضیها بخاطر اینکه اون سمت متغیری از نوع long وجود داشت فکر کردن که کامپایلر بطور خودکار محاسبات رو میبره روی نوع long اما + و < و همچنین + و = دو عبارت مجزا رو تشکیل میدن و ربطی به هم ندارن.
🚁 Hicte Blog | (smm)
تبدیلهای حسابی معمول و ارتقای اعداد صحیح
[قسمت آخر] [لینک به قسمت سوم]
تبدیلهای حسابی معمول، قواعد signed و unsigned:
تو قسمت اول در مورد اولویت بندی انواع استاندارد موقع UAC صحبت کردیم.
حالا اگه تو عبارتی یه نوع باعلامت و نوع دیگه بدون علامت باشه اولویتها چطور تعیین میشه؟
وقتی یه عملوند signed و اون یکی unsigned باشه، قانون کلی اینه:
اگه نوع unsigned رتبهای برابر یا بالاتر از نوع signed داشته باشه، عملوند signed به unsigned تبدیل میشه.
بیاین یه مثال ازش ببینیم:
#include <stdio.h>
int main() {
int a = -1;
unsigned int b = 1;
if (a < b)
printf("correct.\n");
else
printf("Bug!\n");
return 0;
}
تو عبارت
a < b طبق قوانین UAC نوع a موقتا به unsigned int تبدیل میشه. خب وقتی مقدار -1 بخواد تو یه متغیر unsigned int قرار بگیره چی میشه؟ مقدارش برابر با UINT_MAX میشه! [بزرگترین عددی که داخل یه متغیر unsigned int جا میشه]اگه نوع int چهار بایتی باشه نمایش دودویی -1 میشه:
1111 1111 1111 1111 1111 1111 1111 1111
حالا اگه همین بیتها به عنوان نوع unsigned int بخوان تفسیر بشن نمایش دهندهی عدد 4,294,967,295 هستن!
خلاصه حواستون باشه.
قبل شروع این صحبتا یه کدی تو چنل گذاشته بودم با یه نظرسنجی که میتونین از اینجا ببینین:
https://t.me/HicteBlog/1402
خب در مورد این کد ما توی خط ۶ و خط ۷ اورفلو داریم!
وقتی عبارت INT_MAX + 3 اجرا میشه، دو سمت عملگر + هر دو از نوع int هستن پس عملگر + محاسبات رو تو فضای int انجام میده و نتیجهی نهایی رو بصورت int برمیگردونه بدون اینکه ارتقایی رخ بده.
طبیعتا وقتی 3 رو به ماکسیمم مقداری که توی نوع int میتونه ذخیره بشه اضافه کنیم دیگه قابلیت این رو نداره که تو همون نوع int جا بگیره و اورفلو رخ میده.
شاید بعضیها بخاطر اینکه اون سمت متغیری از نوع long وجود داشت فکر کردن که کامپایلر بطور خودکار محاسبات رو میبره روی نوع long اما + و < و همچنین + و = دو عبارت مجزا رو تشکیل میدن و ربطی به هم ندارن.
🚁 Hicte Blog | (smm)
👍3❤1