Наблюдаю в комментах непонимание, поэтому краткая справка для далёких от машинного представления чисел.Знаковые числа и беззнаковые -- это просто наборы бит. Никто не запрещает один и тот же набор бит интерпретировать как знаковый или беззнаковый. Чаще всего, получается примерно такое соответствие:
0 <=> 0
1 <=> 1
...
2^31-2 <=> 2^31-2
2^31-1 <=> 2^31-1
2^31 <=> -2^31
2^31+1 <=> -2^31+1
...
2^32-1 <=> -1
Для знакомых с группами вычетов Z/nZ: знаковые и беззнаковые -- это одна и та же факторизация множества целых чисел, но представители классов выбраны разные. Это как группу Z/3Z можно представлять как множество элементов {0, 1, 2}, а можно как {-1, 0, 1}.
(Кстати обратите внимание, если не сталкивались с этим раньше: abs(abs(x)) не всегда равен x. -2^31 -- это самое большое по модулю число, и оно одно, для него нет положительной пары. Бага системы кодирования чисел, которая иногда становится занозой в заднице).
При этом, что удачно, при таком подходе к кодированию целых, можно использовать одни и те же операции сложения/вычитания для работы как со знаковыми числами, так и с беззнаковыми. Но когда речь заходит об умножении, делении, сравнении чисел, на уровне машинных команд код начинает различаться, в зависимости от знаковости аргументов.
Обсуждаемый бажный memcpy работал с size как со знаковым числом. Для значений меньше чем 2^31 это работало как надо, потому что если такие беззнаковые числа интерпретировать как знаковые, то они по смыслу будут тем же самым. А вот для значений больше либо равных 2^31 уже не работало, потому что если их интерпретировать как знаковые, то получатся отрицательные числа.
И собственно эксплуатация бага свелась к тому, чтобы добиться передачи в memcpy буфера с размером в 2Gb или больше. То есть код, использующий memcpy может быть 100% безбажным, и тем не менее эксплоит будет возможен, при наличии такой бажной реализации memcpy.