Здравствуйте, okman, Вы писали:
O>Кто-нибудь пробовал у себя предложенный тест в VS2015/2017? O>У меня за 20 минут ни разу так и не упало (Windows 10'1709, VS2015 update 3)...
Упало за минуты две. windows 10 1709. VS 2017.6. Релиз 64-бит. 8 ядер.
O>>Кто-нибудь пробовал у себя предложенный тест в VS2015/2017? O>>У меня за 20 минут ни разу так и не упало (Windows 10'1709, VS2015 update 3)... _NN>Упало за минуты две. windows 10 1709. VS 2017.6. Релиз 64-бит. 8 ядер.
А выложите свою ucrtbase.dll, койчо гляну.
Но врядли многопоточность тут виновата — там накрываются крит. секцией операции с хипом и все. А если они по какой то причине не накрываются — был бы пипец всему.
Скорее всего дело в определенной хитрой последовательности маллок-фри. Можно интереса ради накрыть извне критической секцией каждый малок и фри, и если будет воспроизводиться (возможно, пореже), то добавить логику, которая бы както быстренько записывала последовательность операций, чтобы потом проиграть их в одном потоке и получить 100% крэш. А потом уже можно думать и про эксплоит
ЗЫ У меня самого десятки нет, так что все вышеописанное — в ваших руках
Как много веселых ребят, и все делают велосипед...
Могу только подтвердить что приведенный код действительно падает под 10-кой под VS2013 и VS2017. Более того, если malloc заменить на new, то тоже падает, так как new внутри себя зовет malloc.
O>Но врядли многопоточность тут виновата — там накрываются крит. секцией операции с хипом и все. А если они по какой то причине не накрываются — был бы пипец всему. O>Скорее всего дело в определенной хитрой последовательности маллок-фри. Можно интереса ради накрыть извне критической секцией каждый малок и фри, и если будет воспроизводиться (возможно, пореже), то добавить логику, которая бы както быстренько записывала последовательность операций, чтобы потом проиграть их в одном потоке и получить 100% крэш. А потом уже можно думать и про эксплоит O>ЗЫ У меня самого десятки нет, так что все вышеописанное — в ваших руках
Если сделать внешний лок, то падения прекращаются.
O>А выложите свою ucrtbase.dll, койчо гляну.
А зачем? Вот стек вызовов при падении: > ntdll.dll!RtlAllocateHeap()
msvcr120.dll!malloc(unsigned int size) Line 92 + 0x3b bytes C
msvcr120.dll!operator new(unsigned int size) Line 59 + 0x8 bytes C++
В релизе ucrtbase.dll не вызывается. В дебаге вызывается и там лок стоит. И, естественно, не падает.
Как хорошо, что я предусмотрительный, и в своих проектах "для себя" просто выделяю с самого начала большой блок, а потом внутри него работаю ручным аллокатором.
O>>А выложите свою ucrtbase.dll, койчо гляну. V>А зачем? Вот стек вызовов при падении: >> ntdll.dll!RtlAllocateHeap() V> msvcr120.dll!malloc(unsigned int size) Line 92 + 0x3b bytes C V> msvcr120.dll!operator new(unsigned int size) Line 59 + 0x8 bytes C++
Затем что HeapCreate имеет флаг 'HEAP_NO_SERIALIZE' если использовать который — получается не потокобезопасная по дефолту куча.
А еще такой же флаг имеет HeapAlloc — то есть если вызвать HeapAlloc на потокобезопасной куче, передав ему HEAP_NO_SERIALIZE — то вызов будет не потокобезопасный.
Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри
V>В релизе ucrtbase.dll не вызывается. В дебаге вызывается и там лок стоит. И, естественно, не падает.
По ссылке в начальном посте есть стеки с ucrtbase
Вложите тогда свою msvcr120.dll
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
O>Затем что HeapCreate имеет флаг 'HEAP_NO_SERIALIZE' если использовать который — получается не потокобезопасная по дефолту куча. O>А еще такой же флаг имеет HeapAlloc — то есть если вызвать HeapAlloc на потокобезопасной куче, передав ему HEAP_NO_SERIALIZE — то вызов будет не потокобезопасный. O>Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри
Про флаги я в курсе. У меня у самого эта идея появилась в голове. Куча там берется из GetProcessHeap(). Как у нее посмотреть флаги создания?
V>>В релизе ucrtbase.dll не вызывается. В дебаге вызывается и там лок стоит. И, естественно, не падает. O>По ссылке в начальном посте есть стеки с ucrtbase O>Вложите тогда свою msvcr120.dll
Так эта же msvcr120.dll не падает не под 10-кой. А где GetProcessHeap() и то что он возвращает инициализируется?
O>>Затем что HeapCreate имеет флаг 'HEAP_NO_SERIALIZE' если использовать который — получается не потокобезопасная по дефолту куча. O>>А еще такой же флаг имеет HeapAlloc — то есть если вызвать HeapAlloc на потокобезопасной куче, передав ему HEAP_NO_SERIALIZE — то вызов будет не потокобезопасный. O>>Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри V>Про флаги я в курсе. У меня у самого эта идея появилась в голове. Куча там берется из GetProcessHeap(). Как у нее посмотреть флаги создания?
Я и так скажу — GetProcessHeap куча потокобезопасная. Надо ставить бряку на RtlAllocateHeap и смотреть чему равен rdx.
O>>По ссылке в начальном посте есть стеки с ucrtbase O>>Вложите тогда свою msvcr120.dll V>Так эта же msvcr120.dll не падает не под 10-кой. А где GetProcessHeap() и то что он возвращает инициализируется?
Она в PEB, инициализируется на запуске процесса в LdrpInitialize.
Как много веселых ребят, и все делают велосипед...
O>>Затем что HeapCreate имеет флаг 'HEAP_NO_SERIALIZE' если использовать который — получается не потокобезопасная по дефолту куча. O>>А еще такой же флаг имеет HeapAlloc — то есть если вызвать HeapAlloc на потокобезопасной куче, передав ему HEAP_NO_SERIALIZE — то вызов будет не потокобезопасный. O>>Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри V>Про флаги я в курсе. У меня у самого эта идея появилась в голове. Куча там берется из GetProcessHeap(). Как у нее посмотреть флаги создания?
ладненько, тогда эксперимент 2: все тоже самое, но вместо malloc — HeapAlloc(GetProcessHeap(), 0, 4096) а вместо freee — HeapFree(GetProcessHeap(), 0, ...)
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
O>>>Затем что HeapCreate имеет флаг 'HEAP_NO_SERIALIZE' если использовать который — получается не потокобезопасная по дефолту куча. O>>>А еще такой же флаг имеет HeapAlloc — то есть если вызвать HeapAlloc на потокобезопасной куче, передав ему HEAP_NO_SERIALIZE — то вызов будет не потокобезопасный. O>>>Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри V>>Про флаги я в курсе. У меня у самого эта идея появилась в голове. Куча там берется из GetProcessHeap(). Как у нее посмотреть флаги создания? O>ладненько, тогда эксперимент 2: все тоже самое, но вместо malloc — HeapAlloc(GetProcessHeap(), 0, 4096) а вместо freee — HeapFree(GetProcessHeap(), 0, ...)
К сожалению пока не могу продолжить эксперимент, так как чудесным образом оно перестало падать. Не падает ни c malloc, ни c new... никак... чудеса
O>>>>А еще такой же флаг имеет HeapAlloc — то есть если вызвать HeapAlloc на потокобезопасной куче, передав ему HEAP_NO_SERIALIZE — то вызов будет не потокобезопасный. O>>>>Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри V>>>Про флаги я в курсе. У меня у самого эта идея появилась в голове. Куча там берется из GetProcessHeap(). Как у нее посмотреть флаги создания? O>>ладненько, тогда эксперимент 2: все тоже самое, но вместо malloc — HeapAlloc(GetProcessHeap(), 0, 4096) а вместо freee — HeapFree(GetProcessHeap(), 0, ...) V>К сожалению пока не могу продолжить эксперимент, так как чудесным образом оно перестало падать. Не падает ни c malloc, ни c new... никак... чудеса
мб сработал appcompatibility и включил эту приблуду: https://msdn.microsoft.com/en-us/library/windows/desktop/dd744764(v=vs.85).aspx
попробуйте запустить под другим именем ехешника
Как много веселых ребят, и все делают велосипед...
O>>мб сработал appcompatibility и включил эту приблуду: https://msdn.microsoft.com/en-us/library/windows/desktop/dd744764(v=vs.85).aspx O>>попробуйте запустить под другим именем ехешника V>Нет, такая служба не работает — проверил. Проблема просто перестала воспроизводится. они просто через телеметрию увидели что тебя это беспокоит и отключили этот бэкдор
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Videoman, Вы писали:
V>Здравствуйте, ononim, Вы писали:
O>>мб сработал appcompatibility и включил эту приблуду: https://msdn.microsoft.com/en-us/library/windows/desktop/dd744764(v=vs.85).aspx O>>попробуйте запустить под другим именем ехешника
V>Нет, такая служба не работает — проверил. Проблема просто перестала воспроизводится.
Попробуйте в 64-битной версии.
Падает гораздо быстрее чем 32-бит.
Здравствуйте, ononim, Вы писали:
O>>>Затем что HeapCreate имеет флаг 'HEAP_NO_SERIALIZE' если использовать который — получается не потокобезопасная по дефолту куча. O>>>А еще такой же флаг имеет HeapAlloc — то есть если вызвать HeapAlloc на потокобезопасной куче, передав ему HEAP_NO_SERIALIZE — то вызов будет не потокобезопасный. O>>>Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри V>>Про флаги я в курсе. У меня у самого эта идея появилась в голове. Куча там берется из GetProcessHeap(). Как у нее посмотреть флаги создания? O>ладненько, тогда эксперимент 2: все тоже самое, но вместо malloc — HeapAlloc(GetProcessHeap(), 0, 4096) а вместо freee — HeapFree(GetProcessHeap(), 0, ...)
Падает в 64-бит: > ntdll.dll!RtlpLowFragHeapAllocFromContext() Unknown
ntdll.dll!RtlpAllocateHeapInternal() Unknown
Здравствуйте, ononim, Вы писали:
O>>>А выложите свою ucrtbase.dll, койчо гляну. V>>А зачем? Вот стек вызовов при падении: >>> ntdll.dll!RtlAllocateHeap() V>> msvcr120.dll!malloc(unsigned int size) Line 92 + 0x3b bytes C V>> msvcr120.dll!operator new(unsigned int size) Line 59 + 0x8 bytes C++ O>Затем что HeapCreate имеет флаг 'HEAP_NO_SERIALIZE' если использовать который — получается не потокобезопасная по дефолту куча. O>А еще такой же флаг имеет HeapAlloc — то есть если вызвать HeapAlloc на потокобезопасной куче, передав ему HEAP_NO_SERIALIZE — то вызов будет не потокобезопасный. O>Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри
O>>>>Так что анализ кода позволит понять это косяк ucrtbase (использование таких флагов) или поломали чтото внутри V>>>Про флаги я в курсе. У меня у самого эта идея появилась в голове. Куча там берется из GetProcessHeap(). Как у нее посмотреть флаги создания? O>>ладненько, тогда эксперимент 2: все тоже самое, но вместо malloc — HeapAlloc(GetProcessHeap(), 0, 4096) а вместо freee — HeapFree(GetProcessHeap(), 0, ...) _NN>Падает в 64-бит: >> ntdll.dll!RtlpLowFragHeapAllocFromContext() Unknown _NN> ntdll.dll!RtlpAllocateHeapInternal() Unknown
жжжжопауть до чего наделла страну довел
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Коваленко Дмитрий, Вы писали: КД>Запустил "x64 release" на 10-ядерном (6950x) — упало и под отладчиком и при запуске из под cmd.exe. Падает достаточно быстро.
Переписал код, чтобы напрямую использовались HeapCreate, HeapDestroy, HeapAlloc, HeapFree
#include"stdafx.h"#include <iostream>
#include <thread>
#include <conio.h>
#include <Windows.h>
using namespace std;
#define MAX_THREADS 100
HANDLE g_HEAP=NULL;
void task(void)
{
while (true)
{
char *buffer;
buffer = (char *)HeapAlloc(g_HEAP,0,4096);
if (buffer == NULL)
{
cout << "malloc error" << endl;
}
HeapFree(g_HEAP,0,buffer);
}
}
int main(int argc, char** argv)
{
g_HEAP=::HeapCreate(0,8*1024*1024,0);
if(!g_HEAP)
{
cout<<L"HeapCreate failed: "<<::GetLastError()<<endl;
return -1;
}
thread some_threads[MAX_THREADS];
for (int i = 0; i < MAX_THREADS; i++)
{
some_threads[i] = thread(task);
}
for (int i = 0; i < MAX_THREADS; i++)
{
some_threads[i].join();
}
if (!::HeapDestroy(g_HEAP))
{
cout<<L"HeapDestroy failed: "<<::GetLastError()<<endl;
}
_getch();
return 0;
}
Падает скатина! И под cmd.exe и под отладчиком!
Exception thrown at 0x00007FFFC9F7678A (ntdll.dll) in ConsoleApplication1.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
Стек падения.
> ntdll.dll!RtlFreeHeap() Unknown
ConsoleApplication1.exe!task() Line 24 C++
[Inline Frame] ConsoleApplication1.exe!std::_Invoker_functor::_Call(void(*)() &&) Line 232 C++
[Inline Frame] ConsoleApplication1.exe!std::invoke(void(*)() &&) Line 232 C++
[Inline Frame] ConsoleApplication1.exe!std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl*)(void)>,std::default_delete<std::tuple<void (__cdecl*)(void)> > > >::_Execute(std::tuple<void (__cdecl*)(void)> &) Line 240 C++
[Inline Frame] ConsoleApplication1.exe!std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl*)(void)>,std::default_delete<std::tuple<void (__cdecl*)(void)> > > >::_Run(std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl*)(void)>,std::default_delete<std::tuple<void (__cdecl*)(void)> > > > *) Line 247 C++
ConsoleApplication1.exe!std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl*)(void)>,std::default_delete<std::tuple<void (__cdecl*)(void)> > > >::_Go() Line 232 C++
ConsoleApplication1.exe!std::_Pad::_Call_func(void * _Data) Line 211 C++
ucrtbase.dll!thread_start<unsigned int (__cdecl*)(void * __ptr64)>() Unknown
kernel32.dll!BaseThreadInitThunk() Unknown
ntdll.dll!RtlUserThreadStart() Unknown
Надо с CreateThread/beginthread еще попробовать.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, _NN_, Вы писали:
_NN>Как оказывается начиная с Windows 10 Creators Update (1703) функция HeapAlloc не потокобезопасна, а следовательно и malloc.
Windows 10, сборка 1809, обновлял в конце мая 2019.
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Здравствуйте, _NN_, Вы писали:
_NN>>Как оказывается начиная с Windows 10 Creators Update (1703) функция HeapAlloc не потокобезопасна, а следовательно и malloc.
КД>Windows 10, сборка 1809, обновлял в конце мая 2019.
КД>Не падает.
У меня на 1903 не падает тоже, но ничего впереди 1909 и 2003, там всё может быть =)
Здравствуйте, _NN_, Вы писали:
КД>>Windows 10, сборка 1809, обновлял в конце мая 2019.
КД>>Не падает. _NN>У меня на 1903 не падает тоже, но ничего впереди 1909 и 2003, там всё может быть =)
Ты на Pro сидишь? Проблем нет?
Думаю обновиться до 19.03, но стрёмно — тут пугают адскими проблемами с последними обновлениями.
С 1803 я назад откатывался.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, _NN_, Вы писали:
_NN>Как оказывается начиная с Windows 10 Creators Update (1703) функция HeapAlloc не потокобезопасна, а следовательно и malloc.
Это еще ладно — софта, использующего HeapAlloc, неимоверно много, если до сих пор катастрофы не случилось, то глюк достаточно редкий и специфичный. Ну и чинят такое достаточно быстро, как только выплывает.
А я давно и плотно работаю со звуковой подсистемой (AudioSrv, AudioDG, Kernel Streaming) — там уже лет двадцать живут древние косяки, когда что-то или работает не по документации (при этом исправлять как поведение, так и документацию никто не собирается), или вообще идут некорректные операции (неправильные значения флагов, мусор в полях структур и т.п.). Поскольку вся эта кухня тестируется только на родных драйверах от самой MS, которые имеют одну и ту же логику (поскольку пишутся по одному шаблону), сама с собой она работает достаточно стабильно, и ребятам этого вполне достаточно. Когда сторонние разработчики начинают спрашивать, что происходит, оттуда выкатывают классические "ну у нас-то все работает!".
А еще я периодически гоняю их собственные звуковые драйверы под их собственными тестами из WLK, и еще ни разу весь комплект тестов не завершился успешно.
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Здравствуйте, _NN_, Вы писали:
КД>>>Windows 10, сборка 1809, обновлял в конце мая 2019.
КД>>>Не падает. _NN>>У меня на 1903 не падает тоже, но ничего впереди 1909 и 2003, там всё может быть =)
КД>Ты на Pro сидишь? Проблем нет?
Я вообще не припомню проблем с обновлением 10ки уже давно.
Как раз в 1903 с июньским обновлением наконец починили надоедливую ошибку, которая была ещё с 7-ки.
Sign out тупо зависал.
А вт у меня такой вопрос. Кто-нибудь когда-нибудь эту потокобезопасность вообще гарантировал?
C++ до недавнего времени вообще вроде ничего не знал про потоки.