Я сегодня хотел лишний мусор из проекта выкинуть. Там для Gradle написаны какие-то мутные штуки в
buildSrc, и вот они мешаются и болят при каждой миграции. Договорились их удалить.
Но их нельзя просто так выбросить. Там написан немаленький и важный кусок работы, который не был доведён до конца. У нас есть тесты, которые проверяют, что, если ты сериализуешь структуру в плюсах или в C#, а потом присылаешь в Java, то она работает как надо, и всё правильно трекается и ничо не падает.
И вот эти тесты очень рукожопо были сделаны (таски на Gradle для компиляции других языков — это мрак и мутево, да), и поэтому к CI их никто прикрутить не сподобился, инструкцию по запуску не написал, и их уже пару лет как никто не запускал вообще. А к тому же чел, который их писал, уволился давно. И тот, кто его менторил по этой задаче, тоже уволился :)
Ну и вот, кароч, я туда залез, разобрался с Gradle, кое-как научился их запускать, подновил билд, новую версию билд-тулов принёс (потому что текущее всё заросло паутиной уже и не работает). Запускаю эти тесты — а они еблысь и падают. Говорят, у массива размер отрицательный.
Вот в этом коде.
Я его сперва обмазал проверкой на отрицательность, а потом увидал, что она выше уже написана. Ну, короче, понятное дело, там на самом деле пришёл размер положительный в
char, но в байтах он уже в
int не помещается. И, понятное дело, никто на самом деле в тестах таких огромных строк не присылает.
Так что пришлось научиться это дебажить (а там Java-процесс стартуется из другого java-процесса, и это вообще гемор, кароч, всё это нормально отлаживать, но я научился и напишу доку). И вот тогда я увидел, что у нас там какая-то натуральная ебатория происходит.
Сишарп сериализует
вот такую херню, а Котлин пытается десериализовать. И у него по дороге кто-то крадёт четыре байта!
Ну, это я так сначала решил, потому что
UnsafeBuffer реально unsafe и как-то мутно написан; на самом-то деле там не крадёт четыре байта, а докладывает ажно двенадцать байт лишних.
Копался дальше, сравнивал код сгенерированных сериализаторов — неа, одинаковые, абсолютно симметричные. Непонятно, откуда лишние двенадцать байт.
Но потом разобрался, конечно: оказалось, что C# сериализует этот тип полиморфным сериализатором, который пишет в сокет сначала восьмибайтный RdId (ну, можно сказать что хэш в данном случае), а потом ещё четыре байта на длину тела полиморфного объекта. А на принимающей стороне про полиморфность забыли, и эти 12 байт поленились прочитать.
Но, похоже, это ломается только в реально безумных специфических случаях: если у тебя объявлено свойство, которое имеет не базовый, а наследованный тип, вот как ниже
property("polymorphic_open", OpenDerived).