HICTE Blog
1.13K subscribers
432 photos
140 videos
8 files
687 links
گروهمون: @HicteGroup

دسته بندی پست‌ها: t.me/HicteBlog/743
Download Telegram
😁18
#سی

تبدیل‌های حسابی معمول و ارتقای اعداد صحیح

یکی از رفتارهای زبان 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👍61
#میم

توزیعی که تو فلشه چیه؟

🚁 Hicte Blog | (smm)
🤣14
#سی

تبدیل‌های حسابی معمول و ارتقای اعداد صحیح

[قسمت دوم] [لینک به قسمت اول]

قبل از اینکه UAC بررسی بشه، یه مرحله‌ی مقدماتی وجود داره؛ ارتقای اعداد صحیح.


ارتقای اعداد صحیح (Integer Promotion):
هر نوع داده‌ای که جایگاه پایین‌تری از int داشته باشه [یعنی _Bool و char و short] به طور خودکار به int ارتقا پیدا میکنه، حتی اگه هیچ متغیری از نوع int تو عبارت وجود نداشته باشه.

پردازنده‌های مدرن برای کار با مقادیر int بهینه شدن. بنابراین استاندارد C تعیین کرد که همه محاسبات حداقل در سطح int انجام بشن.

ارتقا روی هر عملوند به صورت مجزا اتفاق میافته. حتی یه عبارت ساده مثل c + c که فقط یه char داره، نتیجه‌اش int هست.

بر خلاف تبدیل‌های حسابی معمول، ارتقای اعداد صحیح تو همه‌ی عملگرها اتفاق میفته حتی عملگرهایی مثل ~ که فقط یه عملوند دارن.

استثناها عملگرهای ++، --، sizeof و عملگر انتساب یا همون = هستن که براشون ارتقای اعداد صحیح رخ نمیده. چون sizeof که کلا با مقدار عملوندش کاری نداره و اندازه‌ی نوع متغیر رو محاسبه میکنه، ++ و -- هم مستقیما روی همون متغیر مینویسن، عملگر انتساب (=) هم منطقا نباید به نوع عملوند سمت چپش دست بزنه پس کلا کاری به این موضوع نداره.

🚁 Hicte Blog | (smm)
👍4
#میم

فلش میم قبلی هم معلوم شد چه توزیعی بود!
debian for lesbian

🚁 Hicte Blog | (smm)
🤣12🤷‍♀1🐳1🍓1
🌚10🤣5👀2😁1😍1
#سی

تبدیل‌های حسابی معمول و ارتقای اعداد صحیح

[قسمت سوم] [لینک به قسمت دوم]

ارتقای اعداد صحیح، قواعد 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
#میم
eMac
Emacs

🚁 Hicte Blog | (smm)
😁101🔥1
🥰11😁10💅1
👍8😁2🤡1
#میم
Linux user: ⬆️

🚁 Hicte Blog | (M D)
😁16
#خبر

تعداد زیادی از پکیج‌هایی که تو مخزن 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)
👍32🙏1
😁13👍4
🤣23
#سی

تبدیل‌های حسابی معمول و ارتقای اعداد صحیح

[قسمت آخر] [لینک به قسمت سوم]

تبدیل‌های حسابی معمول، قواعد 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)
👍31
😁15🤣2
#ابزار_لینوکس

batman 🦇
واسه اینکه manpageها رو شیک تر و با رنگ و لعاب ببینین میتونین از بتمن کمک بخواین!

با نصب بسته‌ی bat-extras چندتا اسکریپت آماده در اختیارتون قرار میگیره واسه ادغام کردن bat [که اینجا معرفی کرده بودم] با چندتا ابزار دیگه.

یکی از این اسکریپت‌ها batman هست که از bat به عنوان formatter برای نشون دادن manpageها استفاده میکنه.

# pacman -S bat-extras
$ batman batman

لینک گیتهاب
🚁 Hicte Blog | (smm)
👍3🔥1
#کتاب

Hands-On Network Programming with C

Author: Lewis Van Winkle
Edition: 1st
Date: May 2019
Publisher:‎ Packt Publishing
Length: 478 pages


Amazon 👀
Download 😉

🚁 Hicte Blog | (smm)
🔥3👍2
HICTE Blog
#کتاب Hands-On Network Programming with C Author: Lewis Van Winkle Edition: 1st Date: May 2019 Publisher:‎ Packt Publishing Length: 478 pages Amazon 👀 Download 😉 🚁 Hicte Blog | (smm)
توضیحات:

A comprehensive guide to programming with network sockets, implementing Internet protocols, designing IoT devices, and much more with C

Network programming, a challenging topic in C, is made easy to understand with a careful exposition of socket programming APIs. This book gets you started with modern network programming in C and the right use of relevant operating system APIs.

This book covers core concepts, such as hostname resolution with DNS, that are crucial to the functioning of the modern web. You'll delve into the fundamental network protocols, TCP and UDP. Essential techniques for networking paradigms such as client-server and peer-to-peer models are explained with the help of practical examples. You'll also study HTTP and HTTPS (the protocols responsible for web pages) from both the client and server perspective. To keep up with current trends, you'll apply the concepts covered in this book to gain insights into web programming for IoT. You'll even get to grips with network monitoring and implementing security best practices.

By the end of this book, you'll have experience of working with client-server applications, and be able to implement new network programs in C.

What you will learn

    Uncover cross-platform socket programming APIs
    Implement techniques for supporting IPv4 and IPv6
    Understand how TCP and UDP connections work over IP
    Discover how hostname resolution and DNS work
    Interface with web APIs using HTTP and HTTPS
    Acquire hands-on experience with Simple Mail Transfer Protocol (SMTP)
    Apply network programming to the Internet of Things (IoT)

Who this book is for

If you're a developer or a system administrator who wants to enter the world of network programming, this book is for you. Basic knowledge of C programming is assumed.