Дэниел Cтенберг (Daniel Stenberg), автор утилиты для получения и отправки данных по сети curl, объявил о прекращении использования функции strcpy() в кодовой базе проекта и запрете применения данной функции в дальнейшем. Решение является продолжением инициированного в прошлом году отказа от использования функции strncpy(), копирующей заданное число байт из входящей строки. Применение strncpy() создавало опасность возникновения ошибок из-за пропуска нулевого символа в конце строки или добавочного заполнения нулями...Подробнее: https://www.opennet.dev/opennews/art.shtml?num=64532
Молодцы, хорошее и safe изменение!
Очень affordable
А всего-то нужно было Кернигана-Ритчи прочитать.
И иконку перед монитором чтобы она защищала написанный код.
А могли бы использовать C++ и не пилить велосипед со строками...
а могли бы использовать питон и не заморачиваться вообще, а могли бы заплатить денег индусам и им бы все накодили, а могли бы найти гадалку чтобы она им искала ошибки через спиритические сеансы, ....сколько возможностей упущенно, ай яй яй
> а могли бы заплатить денег индусам и им бы все накодилиРади того, чтобы строку скопировать в другую строку? Им (плательщикам) уже ничто не поможет.
Поясню, программирование на чистом Си похоже на поэзию. Когда вы пишите стихи, люди жившие до вас много раз писали о том, о чём пишите Вы. Но данный факт не является причиной того что не надо писать стихи.Что касается технической стороны, C++ не нужен. В учебниках и Интернете много всяких идиом и готовых функций на Си, которые программист может тупо пере-использовать. А если программсит напишет свою функцию, тоже неплохо. Во всяком случае это называется свободный выбор, а не велосипед.
Программирование на чистом Си похоже на письмо по слогам.
Самурай без меча подобен самураю с мечом, но без меча.
Но не все хотят быть самураями. Поэтому сейчас для микроконтроллеров мало кто пишет на ассемблере.
> Поясню, программирование на чистом Си похоже на поэзию.Абсолютно согласен. Мне напоминает Маяковского и Блока. Причем эстетика, внешний вид текста - основа всего остального.
Но есть отдельные личности, которые из совершенного инструмента делают непотребство (с примером можно ознакомиться в соседней теме), а в случае неизбежной неудачи обвиняют инструмент.
Можно примеры?
> Абсолютно согласен. Мне напоминает МаяковскогоДля написания на СИ тоже нужно быть куколдом и плаксой?
> Причем эстетика, внешний вид текста - основа всего остального.
Т.е главное как оно выглядит, как работает уже не важно))?
> Но есть отдельные личности, которые из совершенного инструмента делают непотребство (с примером можно ознакомиться в соседней теме),
Т.е все СИшники.
Глупейшие ошибки встречаются в ядре линукс, криптографичечких библиотеках (ssl/ssh), стандартных библиотеках (glibc), просто библиотеках (libxml, libwebp), шрифтах (freeType), утилитах (curl, sudo) ...Возможно где-то есть НАСТОЯЩИЕ СИшники, но очевидно код они не пишут.
> а в случае неизбежной неудачи обвиняют инструмент.
Если неудача неизбежна, то возможно инструмент овно)?
Си и эстетика... сомнительно совместимые понятия. Но Раст, в этом плане, ещё хуже.
Рано или поздно и curl на Rust перепишут.
И это будет отвратительно
Уточнение:Начнут переписывать.
Уточнение:второй раз
Его и первый раз не начали, там растеры сделали какой-то минимальный бекенд и забросили, думая что Даниэль будет сам поддерживать его. А он не стал и просто выбросили его - https://daniel.haxx.se/blog/2024/12/21/dropping-hyper/
Он же прямо говорит что вместе с теми кто этот бекенд и добавил решили что оно не нужно, функциональность слишком сильно дублирует то что в curl уже есть, не давая особых преимуществ, но при этом усложняя сборкуВсем желающим заменить curl на Rust - hyper имеет своё сишное апи, без лишней прослойки в форме api curl: https://docs.rs/hyper/latest/hyper/ffi/index.html
Ох уж эти тысячи глаз
Если уже и переписывать, то на Go. Потому что использование системного языка для простой утилиты выглядит как из пушки по воробьям.
Curl это библиотека - libcurl, а не утилита. С ней линкуется софт, если нужен http/ftp/smtp/pop3/ldap/ssh протоколы. Так что не катит тут твой гоу с его GC, рантаймом и непонятным API.
Всегда использовали лишь как утилиту. А какой именно софт с libcurl линкуется?
Начнут переписывать.
Где бенчмарки?
Ну вот да, если нет managed строк - явная передача размеров буферов - лучшее решение.
>Кроме того, прекращение использования strcpy позволит избавиться от потока ложных сообщений об уязвимостях из-за некорректных срабатываний AI-инструментов, считающих наличие strcpy() уязвимостью без учёта имеющихся в коде проверок.Это какой-то.... позор?
Что да, то да. Когда термометр на мороженой рыбе показывает +50 - стоит выкинуть термометр.
С другой стороны, заявляется, что качество кода улучшено.
из-за некорректных срабатываний AI-инструментов, считающих наличие strcpy() уязвимостью
очередная победа "безопасности" над здравым смыслом.
осталось ещё отключить интернет.
"False positives" существовали всегда, если "эксперты по безопасности", проверяющие код AI-инструментами, об этом не в курсе, то это вопрос квалификации таких "экспертов". (Это, конечно же, не отменяет того факта, что AI в его нынешнем состоянии - срущий под себя младенец, пригодный только для выкачивания денег из инвесторов)
>автор утилиты ..., объявил оОчевидно, что если Данила еще немного подумает, то придет к единственно верному решению - переписать вообще на другом актуальном языке.
Зря вы так. C тут то, что доктор прописал. На python слишком медленно будет.
Ну, питон как-бы популярный, но думаю, сейчас уже не актуальный.
> Ну, питон как-бы популярныйи самое главное - в количестве пробелов не ошибиться.
Не совсем понятно, зачем ему что- то переписывать на C#
Да, не, это не слишком актуально сейчас
Он уже пытался, но неосилил выносить нытье любителей некроплатформ.
Так что пусть хлебает щии(т) полной ложкой и выдумывает костыли для подпорки проекта.
Бог любит троицу, так-что еще не все потеряно
> Применение strncpy() создавало опасность возникновения ошибок из-за
> пропуска нулевого символа в конце строки или добавочного заполнения
> нулями.Шикарный йазычог с офигенно продуманной стандартной либой :)
Прям все сделано для людей.> Замена strcpy() на curlx_strcopy() произведена, так как существует
> вероятность человеческой ошибки, приводящей к разделению кода с
> проверкой/выделением памяти и вызовом strcpy(), например, при
> необдуманном переносе лишь части кода или вставки кода между проверкой
> и вызовом strcpy()Хехе, classic.
Что забавно, даже новая curlx_strcopy не возвращает ошибку, если размеры не подходящие, а молча копирует нулевой символ.
> Хехе, classic.в топку любые функции в стд, которые используют внутри себя другие функции. Эти функции фактически обертки над memset, пусть эти обертки пишет сам программист под свои задачи, по факту если это функция в стандартной библиотеке, то по существу там все входные параметры должны быть проверены на корректность, и указатели и длины, а тут что? - одни предположения. Мракобесие!
правка: memcpy, неважно, суть в общем ясна.
> Шикарный йазычог с офигенно продуманной стандартной либой :)Никто не мешает использовать более безопасные инструкции, вместо устаревших. Microsoft ещё в ранних Visual Studio сделала, чтобы компилятор ругался. Ты что ли не стареешь, офигенный продуман.
> Microsoft ещё в ранних Visual Studio сделала, чтобы компилятор ругался.Он бы ругался, когда во все проекты телеметрию добавляет.
Для исключения уязвимостей в коде на Си достаточно средств, предоставляемых самим Си? Ай, беда-трагедия, как же тогда прогресс двигать, если можно без модных язычков обходиться?
А поцаны, писавшие всю жизнь на паскале и использовавшие для этого string, даже и не знали об этой проблеме. А кто то все еще думает, что паскаль с его строгой типизацией - плохой язык.
string — это который не может быть длиннее 255 символов?
Ты что паскаль последний раз видел когда Ельцин был президентом)?
String is an alias for ShortString, AnsiString or Unicodestring (UTF16) depending on a compiler setting.Т.е оно не просто поддерживает длинные строки, но еще и Unicode.
Чего дырявым ЯП даже не снилось.
> Ты чтоНадо начинать сначала с понятий bounded и unbounded string, потом уже ShortString, AnsiString or Unicodestring (UTF16) :)
> Чего дырявым ЯП даже не снилось.Ты что Сишку видел когда еще Горбачёв был президентом СССР? В Си строки вообще никогда не были ограничены по длинне, и так же 100 лет умеют в юникод.
> В Си строкиА в СИ есть строки? Вот это новость!!!
Специально открыл стандарт, но там никакого string data type нету.
В string.h какие-то недофункции для работы с чарами.> вообще никогда не были ограничены по длинне,
Конечно не ограничены.
Ни по длинне, ни по буферу. Главное не забывать про нуль-терминатор, иначе будет бо-бо.> и так же 100 лет умеют в юникод.
Настолько, что росчитать длину строки в символах для UTF-8 уже проблема.
> А в СИ есть строки? Вот это новость!!!Ну это же вы начали первый. Я вам подыграл немного. Да, в Си нет никаких строк, как и в ассемблере. В асме "строки" это просто массив байт, ровно как и в Си.
> Настолько, что росчитать длину строки в символах для UTF-8 уже проблема.
И какая тут проблема у вас?
> И какая тут проблема у вас?С utf-16 при конвертации в utf-8 нужно заново по строке итерироваться и пересчитывать всё, потому что 2-4 байта в utf-16 это от 1 до 5 байт в utf-8
Вычисления не бесплатные, и требуются во всех программах что взаимодействуют с реальным миром, где в utf-16 данные не хранит никто
> В асме "строки" это просто массив байт, ровно как и в Си.Да, потому сишка это просто переносимый супермакроассемблер созданный для портирования юниксов на следующую PDP. Вопрос зачем писать на этом недоязыке в 2025 остается открытым
> И какая тут проблема у вас?
Проблема что нужно не только бегать до конца строки в поисках заветного \n как для подсчета размера в байтах, а еще и проверять является ли последовательность байтов валидным UTF-character и подсчитывать именно их. А что делать если не валидная?)
И так каждый раз, вместо того, чтобы один раз посчитать при создании и валидации и потом просто использовать это значение.
> но еще и UnicodeВот только utf16, как и все другие языки что добавили поддержку unicode непрозрачно, в 90х годах, а не нормальный utf8
Неа. Строки были динамические еще со времен TP. Причем за временем жизни следить компилятор. А всякие вот эти strблаблабла из Си - это что то из времен, когда выделять память динамически было слишком дорого, а потому или она выделялась на стеке (привет записывание за пределы буффера, бугага), или использовался некий статический буффер (привет thread-unsafe). Как давно это было?А паскаль - эт ваще чудо. Открою большой и жирный секрет. Если заменить объекты на интерфейсы, а TObject на TInterfacedObject - можно вообще обойтись без деструкторов, ибо все время жизни будет отслеживаться компилятором. В Си/С++, насколько я знаю, так нельзя. Там надо все равно _AddRef и _Release ручками вызывать. И привет безопасная работа с памятью для криворуких программистов, которые не знают принципа матрешки - что создал, то надо удалить.
Да, на паскале можно писать почти как на скриптовом языке. Можно создать что то типа TList<TMyInterface>, добавлять туда что то без необходимости очищать это добро унылым кодом типа for I := 0 to FList.Count - 1 do FList[I].Free. И даже можно создавать, едрен батон, анонимные объекты, т.е. что то типа MyFunc(TMyObject.Create).
Паскаль всегда был слишком понятным и эффективным. Если что-то написано - сразу понятно, бред или нет (академический, те физиков и ко, код очень часто бред, просто иногда работает, его в расчет не берём). Очень сложно пускать пыль в глаза, когда Вас легко вывести на чистую воду.
Поэтому Питон, Си, Раст нужны - мозг свой вынесешь, пока разберёшься, что не так работает.
Я сейчас пишу на C/C++. Да, я тормоз. Когда все писали на C, я писал на паскале. Когда все пишут на Rust, я пишу на C/C++. Ну что могу сказать. У C/C++ есть свои плюсы, но и свои минусы, типа невозможности присваивать массивы и необходимости кастовать enum в int. Но если я реально хочу быстро написать какую-то прогу без лишних заморочек и мозголомства - я все равно запускаю Lazarus.У меня есть старый проект на 300к строк, где нет ни одной утечки памяти. А все почему? Потому, что хорошая дисциплина написания кода и волшебный FastMM, который умеет рапортовать ошибки памяти. В том числе и тихие хэап коррапшены, если перейти в фулл дебаг мод. Классно ведь, когда не только утечка памяти показывается, но еще и ГДЕ она происходит?
memccpy ему не понравилась? Занулять строку звучит как лютый костыль всё равно, лучше уж abort кидать чтобы баги быстрее пофиксить связанные с неправильным размером буфера.
Шпасибо за идею, ребята, но таки не лучше. Пусть у меня лучше один запрос завалится с непонятным багом, чем всё приложение.
> Пусть у меня лучше один запрос завалится с непонятным багом, чем всё приложение.А если запрос НЕ завалится?
И просто будет удалённое выполнение кода как в Net-SNMP?Будет лучше)?
Вот что криво в этой реализации - нет отработки варианта slen == dsize и src[slen - 1] == 0. Это вполне себе корректный вариант, который тупо пропущен.
Не трогай! Это на новый год! (следущий)))А вообще это норм, как для сишки.
По хорошему функция должна возвращать ошибку при неверных входных параметрах, но обработку ошибок еще не завезли, так что "и так сойдет"
Охохо, опять strncpy.Вот что она делает, судя по названию? Наверное копирует строку 🤔
Ан нет!
Она копирует не более n ненулевых байтов из источника и добивает буфер до n нулями (но зачем?), ломая инвариант - в буфере после копирования не строка.Отличная функция для строковой библиотеки, чувствуется могучий дедовский дизайн - собрать столько бесполезной функциональности в одной функции.
Ну и что теперь из-за каждого чтения привет мира нужно городить библиотеку на 10 мегабайт? Раньше операционные системы были меньше 10 мегабайт.
>Теперь все вызовы strcpy() заменены на новую функцию curlx_strcopyКакое же гнилое говно эта сишка, что в ней совсем-совсем в стандартной библиотеке вообще ничего юзабельного нет. Менталитет сишников такой же. Сейчас я задействовал одну либу, парсящую один формат, на сишке (от безысходности, на плюсах варианта нет) ... вроде бы превосходно документированную, но ... оказалось, что таки недостаточно документированную, там внутри malloc на mallocе, хотя это совсем не требуется, можно было просто указатель в буфер, которым владеет пользователь API, передать, без каких-либо аллокаций вообще, и то, что функция делает маллоки и что возвращаемые ей значения надо освобождать - это вообще никак недокументировано! А в другой функции есть баг прямо в API, из-за которого использование её функций сразу даёт повреждение кучи из-за путаницы в типах указателей (функция из одной строчки, но там непрозрачный указатель приводится не к тому типу, потому что разраб идиот, решил сэкономить, и внутри либы одну и ту же функцию задействовать для двух разных типов, при этом весь код касаемый другого типа не протестирован вообще, так как второй тип - это плюсовые биндинги, которые автор просто добавил без каких-либо тестов).
> от безысходности
> хотя это совсем не требуется, можно было просто указатель в буфер, которым владеет пользователь API, передать, ....это что за такой синдром выученной беспомощности? Ну пишите сами тот самый парсер, в чем проблема?
> А в другой функции есть баг прямо в API
А у кактуса есть КОЛЮЧКИ! Подумаешь, главное ведь желудок забить, чтобы не урчало.
пс: короче, причем тут Си если описанное выше мракобесие не зависит от языка, а от "потому что разраб идиот", сами ведь утверждаете.
>[оверквотинг удален]
> пользователь API, передать, без каких-либо аллокаций вообще, и то, что функция
> делает маллоки и что возвращаемые ей значения надо освобождать - это
> вообще никак недокументировано! А в другой функции есть баг прямо в
> API, из-за которого использование её функций сразу даёт повреждение кучи из-за
> путаницы в типах указателей (функция из одной строчки, но там непрозрачный
> указатель приводится не к тому типу, потому что разраб идиот, решил
> сэкономить, и внутри либы одну и ту же функцию задействовать для
> двух разных типов, при этом весь код касаемый другого типа не
> протестирован вообще, так как второй тип - это плюсовые биндинги, которые
> автор просто добавил без каких-либо тестов).Начал поносить сишку, а закончил тем что "(от безысходности, на плюсах варианта нет)" - ну т.е. сам криворукий ничего не умеющий дятел, который ждёт что за него всё напишут.
> Решение является продолжением инициированного в прошлом году отказа от использования функции strncpy(), копирующей заданное число байт из входящей строки. Применение strncpy() создавало опасность возникновения ошибок из-за пропуска нулевого символа в конце строки или добавочного заполнения нулями.Каким образом можно пропустить нулевой символ в конце строки и причём тут вообще добавочное заполнение нулями? Если оперировать Си строками без грязных хаков и собственных велосипедов, то нулевой символ никогда не исчезнит. Функция strcpy никогда не теряет нулевой символ. Если после нулевого символа есть дополнительные нулевые символы, это вообще не должно создавать никаких проблем. Если я не прав, приведите пример кода.
Надо же было гражданину отличиться. Отличился.
> Каким образом можно пропустить нулевой символ в конце строкиЭлементарно. godbolt.org/z/znGerE5h6
int main() {
char source[] = "Hello, World!";
char destination[10];
int copy_length = 10;
strncpy(destination, source, copy_length);
printf("Result %s", destination);
return 0;
}Program stdout: Hello, WorHello, World!
Итого - запоротый вывод из-за потерянного \n.
Потому что в сишечке строк нет, а есть убогие char*.
Недавно смотрел код этой библиотеки. Код страшноват даже по меркам си. С модульностью как-то тоже не очень, один здоровый монолит. Даже не ясно, кто в здравом уме будет это поддерживать, если автор отойдёт от дел.
ИИ будет поддерживать.
Новости которые мы заслужили