1. Си / Говнокод #20200

    −47

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    int hardinfo_updata( struct UPINFO * headinfo, struct HARDINFO * hardinfo )
    {
    	char sbuf[128] ;
    	int sn_len = 0 ;
    	char *psn ;
    	
    	printf("%s\n",__FUNCTION__  ) ;
    	memset( sbuf, 0xFF, 128 ) ;
    	if( strcmp( hardinfo->flag, "hardinfo") != 0 )
    	{
    		psn = (char *)hardinfo ;
    		sn_len = *psn ;
    		psn += 1;
    		memcpy( sbuf, psn , 127 ) ;
    	}
    	else
    	{
    		sn_len = hardinfo->sn_len ;
    		memcpy(sbuf, hardinfo->sn, 128 ) ;
    	}
    
    	memcpy( hardinfo, &(headinfo->hardinfo), sizeof( struct HARDINFO ) ) ;
    	hardinfo->sn_len = sn_len ;
    	if( hardinfo->sn_len > 128 ) hardinfo->sn_len = 128 ;
    	memcpy( hardinfo->sn, sbuf, hardinfo->sn_len ) ;
    	
    	memset( 0x30008000, 0xFF, 0x20000 ) ;
    	memcpy( 0x30008000, hardinfo, sizeof( struct HARDINFO ) ) ;
    	memset( sbuf, 0xFF, 128 ) ;
    	sprintf( sbuf, "%s %x %x\0", "nand erase 80000 80000 ;nand write 0x30008000", 0x80000, 0x20000) ;
    	run_command( sbuf,0);
    
    	memset( sbuf, 0, 128 ) ;
    	sprintf( sbuf, "%s %x\0", "nand read  0x31000000 80000 ", 0x20000 ) ;
    	run_command(sbuf, 0 ) ;
    
    	if( memcmp( 0x30008000, 0x31000000, sizeof( struct HARDINFO) ) != 0 )
    	{
    		printf("bootloader data crc error\n") ;
    		return 0 ;
    	}
    	else
    	{
    		printf("update hardinfo is ok\n") ;
    	}
    
    	return 1 ;
    }

    CRC через memcpy. Из пропатченного китайцами u-boot

    Запостил: j123123, 15 Июня 2016

    Комментарии (65) RSS

    • блин, опять memcpy и memcmp спутал(в описании к говнокоду). Не выспался еще. Жаль что описание поправить нельзя
      Ответить
    • Как же бесит объявление переменных в начале большой функции...

      Вот у меня сразу в мозгу триггернулось: "ага, в верхней ветке psn заполнили, а в нижней - нет, если внизу её заюзают - всё распидорасит... а, не юзают, ну и слава богу".
      Ответить
      • соснёте вы когда-нибудь со своим C99
        Ответить
        • Уже C11 давно прижился, а вы всё ещё по 99 страдаете.
          Ответить
        • Да даже c89 позволял описывать переменные в начале блока...
          Ответить
        • C99 вечен и непорочен. Ты умрешь, и прах твой развеется по ветру, а на C99 и дальше будут писать царский код
          Ответить
          • потому что проекты начали в 99-м и переписывать всё с нуля лень?
            Ответить
      • >>Как же бесит объявление переменных в начале большой функции...
        а мне нравится)

        сразу представляю себя таким юникс хакером за PDP в больших очках, клечатой рубашке и с бородой
        Ответить
        • > юникс хакером за PDP в больших очках, клечатой рубашке и с бородой
          http://amturing.acm.org/images/mccarthy-3.jpg

          Смотрит на таких хипстеров с неодобрением
          Ответить
          • >Смотрит на таких хипстеров с неодобрением
            Потому что заедушные сишкобляди?
            Ответить
    • Ну верификация через memcmp тут как раз одно из самых адекватных мест, к которому особо не доебёшься...
      // мы стираем флешку, поэтому буфер под null-terminated строку с
      // командой надо обязательно заполнить 0xFF...
      memset(sbuf, 0xFF, 128);
      sprintf(sbuf, "%s %x %x\0", "nand erase 80000 80000 ;nand write 0x30008000", 0x80000, 0x20000);
      Ответить
      • А нет ли опасений по поводу того, что после memset/memcpy у проца может быть кэшнута та память, и когда делаем memcmp то сравниваться будет не та память, которая на NAND флеше, а которая в кэше проца?
        Ответить
        • Ну будем надеяться, что 0x30000000 - uncachable зона.

          Ну а если кешируется, и мы там можем увидеть кусок старых данных от старой прошивки - ну тут только какой-то системнозависимой инструкцией кеш прочищать... memcmp не виноватый, тут совершенно любая проверка обосрётся.
          Ответить
          • >memcmp не виноватый, тут совершенно любая проверка обосрётся.

            Ну если сделать нечто вроде
            writeflash(buf1, addr, 128);
            readflash(buf2, addr, 128);
            memcmp(buf1, buf2, 128);

            То все должно пройти гладко. Вообще, я не особо курил код этого u-boot, может таких извратов делать не надо
            Ответить
            • > Ну если сделать нечто вроде
              Ну здесь же именно так и делают :)

              З.Ы run_command() это чё-то типа system()?
              Ответить
              • Это когда ты подцепляешься через UART к устройству, то там консолечка, ты вводишь всякие команды, и эти команды обрабатывает этот самый run_command
                Ответить
        • З.Ы. А, да тут же к самому NAND'у никто не лезет. Просто просят какую-то внешнюю тулзу записать туда байтики с адреса 0x30008000 и прочитать их на адрес 0x31000000. Тогда вообще всё ок.
          Ответить
          • Если интересно порыться в этом г-не, могу скинуть исходники бутлодера, они не секретные
            Ответить
            • Да не, лень.
              Ответить
              • да. ты угадал. в у-бууте есть комманды, и этот кусок кода ими пользуется.

                так как у-буут стартует рано, и как правило архитектура известна, то и лэйаут памяти тоже известен - почему в у-бууте использование фиксированых хардкоженых адресов памяти (0x30008000, 0x31000000) и популярно.

                код на самом деле не так плох. учитывая что писали хардварщики - так почти идеал. и сообщение об ошибке и не так плохо: можно было бы "consistency check" написать - но типичные пользователи уже знают CRC ошибки, и просто не имеет смысл их грузить деталями. в конце концов, CRC это дешевая имитация memcmp().
                Ответить
      • Зачем trailing \0?
        Ответить
        • Ну хер их знает, вдруг там у них run_command() может исполнять несколько команд, разделённых нулями...

          Ты лучше объясни, зачем там memset на 0xFF
          Ответить
          • Скорее тут причина в том, что это написано криворукими китайцами
            Ответить
          • Могу только судить по своему опыту с МПЕГ2-ТС.

            Иногда тупо выгодней сделать
            memset(payload, 0xFF, 184);

            и потом заполнить payload, чем
            /* payload goes here */
            while (i < 184) payload[i++] = 0xFF;


            Особенно если payload состоит из 20 байт, ибо по Стандарту, unused bytes shall be set to 0xFF.
            Ответить
            • Но нахуй добивать командную строку 0xFF'ками? :3

              З.Ы. Я понимаю, зачем это делается с бинарными данными.
              Ответить
          • > Ты лучше объясни, зачем там memset на 0xFF

            может копипаситили memset из другого места в коде. некоторые флеши перед программированием надо в 0xFF ставить.
            Ответить
            • > memset( 0x30008000, 0xFF, 0x20000 ) ;
              Видимо вот отсюда пробралось.
              Ответить
            • > перед программированием надо в 0xFF ставить
              Ну скорее просто чтобы не дрочить хвост флешки лишними переключениями 1 -> 0. 0xFF один хер получается только после отдельной команды стирания...
              Ответить
              • насколько я понял (в зависимости от типа шлеша?) у них 1ые биты это просто нормальное состояние флеша, а 0 нужно записывать. но это просто спекуляция, на основании разговоров с хардварщиками. (NOR & NAND - этот NOT в начале означает отрицание и то что единички флешу представлять не надо, а только нолики.)
                Ответить
                • Да, там, емнип, 1 - нет заряда на кондёре, 0 - есть заряд. Отсюда и N.

                  А NOR/NAND - как соединены между собой ячейки. В NOR параллельно (wired-or) и можно любой бит зарядить независимо, но плотность хуёвая, получаются от силы мегабайты. В NAND'е - последовательно (wired-and), поэтому можно записать только всю цепочку разом (единички маскируются, нолики заряжаются), зато лишнего обвеса минимум, можно делать гигабайтные флехи.

                  А выкачивается заряд (забиваются единички) в обоих типах только большими блоками...
                  Ответить
          • >Ну хер их знает, вдруг там у них run_command() может исполнять несколько команд, разделённых нулями...

            Даже если и так, sprintf не будет разбирать строку дальше нуля. Китайцы вероятно решили, что чтобы в буфер попал ноль в конце, надо обязательно "\0" добавить в конце строки скармливаемой этому sprintf, а иначе там сразу после текста полезут эти 0xFF
            Ответить
        • А почему тебя не смущает то, что sprinf там вообще нахрен не нужен? Вот это например
          sprintf( sbuf, "%s %x %x\0", "nand erase 80000 80000 ;nand write 0x30008000", 0x80000, 0x20000) ;

          элементарно заменяется на:
          strcpy(sbuf, "nand erase 80000 80000 ;nand write 0x30008000 0x80000 0x20000");
          Ответить
          • Не, я бы всё-таки sprintf поюзал, чтобы константам имена дать.
            Ответить
            • А еще лучше вызывать те функции, которые этот самый run_command вызывает в ответ на эту говностроку. Но китайцам лень в этой хуйне разбираться, лучше в строку воткнем хуйни и скормим в run_command()
              Ответить
              • Ну там не факт, что они доступны откуда надо и т.п... Но в идеале - да.
                Ответить
                • все там доступно, это загрузчик, а не какая-то там ОС
                  Ответить
                  • Ну это ж static стирать, в хедер прототип выносить и т.п...
                    Ответить
          • может быть планировали в будущем 0x80000 и 0x20000 из переменных окружения брать. sprintf() не мешает.
            Ответить
    • > char sbuf[128] ;
      > char sbuf[заранее_угадай] ;

      Как я сука ненавижу сишколибу для строк
      Ответить
      • Please remove yourself from this bar.
        Ответить
      • > заранее_угадай
        Можно подумать, что в пасцале не так, когда куча недоступна и строки надо на стеке объявлять.
        Ответить
        • Ага. Стандартный паскалевский тип string (который в Дельфи переименовали в ShortString), если не указать размер, эквивалентен string[255].
          Ответить
          • И тут хоть угадывай, хоть не угадывай, больше 255 никак не упихать.
            Ответить
            • 255 хватит всем. Зато угадывать не надо и никто не переполнит.
              Ответить
            • > 255
              256, разве нет?
              Ответить
              • 255. Нулевой байт/символ используется под длину.
                Ответить
                • Цари могут и 256 запихать (заняв нулевой байт не под длину), только библиотечные функции с ними работать не будут.
                  var
                    somearray: array[0..255] of char;
                    somestring: string[255];
                    i: byte;
                  begin
                    for i:= 0 to 255 do
                      somearray[i] := chr(ord('A') + i mod 26); (* Заполним 256 элементов *)
                    move(somearray[0], somestring[0], 256); (* Царь в треде *)
                    for i:=0 to 255 do
                      WriteLn('somestring[', i:3, '] = ', somestring[i])
                  end.


                  http://ideone.com/0fJrLY
                  Ответить
        • Да они хотя бы не вылазят за пределы.
          Ответить
          • $R- $Q- и доступ по индексу. Вы не верите, что похерить память можно в любом адекватном языке? Тогда мы идём к вам.
            Ответить
            • Недавно как раз порчу памяти отлаживал в java script
              Ответить
              • Сглаз еще не расследовал?
                Ответить
              • Как похерить память в пхп и жс?
                Ответить
                • rowhammer
                  Ответить
                  • У меня от rowhammer были oops в ядре
                    Ответить
                    • Прям от js'ного, или от сишного с flush'ем?
                      Ответить
                      • От сишного. js-ный надо под конкретный проц ручками затачивать. Но думаю что и через него можно
                        Ответить
                        • >От сишного.
                          От каких кодов?

                          Уязвимость?
                          Своё говно?
                          Искусственно сделанный тест?
                          Ответить
            • > $R- $Q- и доступ по индексу

              http://risovach.ru/upload/2015/12/mem/palki-v-kolesa_99340943_orig_.jpg
              Ответить
              • Доступ ограничен


                Доступ к запрашиваемому Вами Интернет-ресурсу ограничен в
                соответствии с требованиями законодательства и/или во исполнение
                решения суда.
                Ответить

    Добавить комментарий