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

    −1

    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
    // https://github.com/omonar/nginx-http-auth-digest/blob/38fd7eb04b862636e61b812bbbb8fd2cae4d9ab4/ngx_http_auth_digest_module.c#L910
    
            if (ngx_auth_digest_str2_casecmp(start, 'n', 'c'))
            {
                field = &ngx_http_auth_digest_fields.nc;
    
            } else if (ngx_auth_digest_str3_casecmp(start, 'q', 'o', 'p'))
            {
                field = &ngx_http_auth_digest_fields.qop;
    
            } else if (ngx_auth_digest_str3_casecmp(start, 'u', 'r', 'i'))
            {
                field = &ngx_http_auth_digest_fields.uri;
    
            } else if (ngx_auth_digest_str5_casecmp(start, 'n', 'o', 'n', 'c', 'e'))
            {
                field = &ngx_http_auth_digest_fields.nonce;
    
            } else if (ngx_auth_digest_str5_casecmp(start, 'r', 'e', 'a', 'l', 'm'))
            {
                field = &ngx_http_auth_digest_fields.realm;
    
            } else if (ngx_auth_digest_str6_casecmp(start, 'c', 'n', 'o', 'n', 'c', 'e'))
            {
                field = &ngx_http_auth_digest_fields.cnonce;
    
            } else if (ngx_auth_digest_str6_casecmp(start, 'o', 'p', 'a', 'q', 'u', 'e'))
            {
                field = &ngx_http_auth_digest_fields.opaque;
    
            } else if (ngx_auth_digest_str8_casecmp(start, 'u', 's', 'e', 'r', 'n', 'a', 'm', 'e'))
            {
                field = &ngx_http_auth_digest_fields.username;
    
            } else if (ngx_auth_digest_str8_casecmp(start, 'r', 'e', 's', 'p', 'o', 'n', 's', 'e'))
            {
                field = &ngx_http_auth_digest_fields.response;
    
            } else if (ngx_auth_digest_str9_casecmp(start, 'a', 'l', 'g', 'o', 'r', 'i', 't', 'h', 'm'))
            {
                field = &ngx_http_auth_digest_fields.algorithm;
    
            } else {
                goto skip;
    
            }

    Чем им strcasecmp не угодил?

    Запостил: j123123, 29 Мая 2018

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

    • О хоспаде!
      Ответить
    • Я такой же код видел в VK.

      По какой-то необъяснимой причине победители олимпиад и цари считают что если строку записать как строковый литерал а не как массив чаров то сразу же случится боттлнек.
      Ответить
      • Вот ты у нас как бы умный, "C", насколько я понял, знаешь. Поясни мне, жалкому приверженцу "PHP", что такое строковый литерал и, вообще, в чём говённость вышеприведённого кода? А то у меня в "PHP" всё гораздо проще, без подвыпердов...
        Ответить
    • #define ngx_auth_digest_str2_casecmp(m, c0, c1)                                                   \
          ((m[1] << 8) | m[0] | 0x2020) == ((c1 << 8) | c0)
      
      #define ngx_auth_digest_str3_casecmp(m, c0, c1, c2)                                               \
          ((m[2] << 16) | (m[1] << 8) | m[0] | 0x202020) == ((c2 << 16) | (c1 << 8) | c0)
      
      #define ngx_auth_digest_str5_casecmp(m, c0, c1, c2, c3, c4)                                       \
          ((m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0] | 0x20202020)                               \
              == ((c3 << 24) |(c2 << 16) | (c1 << 8) | c0)                                              \
              && (m[4] | 0x20) == c4

      Оптимудяторы блеать.
      Ответить
      • | 0x20

        '@' == '`'
        '[' == '{'
        '.' == '\n'
        '2' == '\r'
        '4' == '\t'

        Хотя они сравнивают только буквы, так что сойдёт.
        Ответить
        • И много от этого они выиграли в производительности?
          Ответить
          • Они отказались от проверки попадания символа в диапазон - сэкономили на инструкциях сравнения (фактически вычитания и сравнения с нулём) и перехода.

            Возможно, им это нужно не для производительности, а для противодействия time attack: когда присутствуют сравнения, злоумышленник может засечь время и определить, сколько переходов было совершено.
            Ответить
            • так тут проверка против конкретных полей, а не паролей
              Ответить
          • ну, для "username", например, два четырехбайтных сравнения вместо восьми однобайтных: https://godbolt.org/g/HsCqr9
            Ответить
            • Я имею ввиду, нужна ли такая оптимизация.

              ЗЫ. Что делает инструкция rep ret?
              Ответить
              • Префикс rep игнорируется перед нестроковыми инструкциями. В данном случае используется как заполнитель для выравнивания кода.
                Ответить
              • Нагуглил такой код:
                rep ret /* REP to avoid AMD branch prediction penalty */

                Если однобайтовый ret идёт сразу за условным переходом, то на некоторых процессорах AMD K8 и K10 сбивается предиктор инструкций, что приводит к задержке.
                Ответить
                • А чем nop не подходит?
                  Ответить
                  • http://repzret.org/p/repzret/

                    Да, целый сайт посвящён одной проблеме.

                    rep ret -- это одна инструкция (хотя и с префиксом).
                    nop + ret -- это две инструкции.
                    Ответить
                    • x86 кавно, то ли дело ARM.
                      Ответить
                      • Ага, где переключение на набор инструкций Thumb производится путём перехода на нечётный адрес.
                        Ответить
                        • Что плохого? Всё равно в ARM инструкцэи всегда выровнены по словам.
                          Ответить
                          • Пойдёт. Раз младшие биты операторами перехода игнорируются, их можно задействовать для чего-то другого.

                            Только это... необычно. Могут быть волшебные эффекты при переходе на вычисленный адрес. Интел в случае ошибки при вычислении просто перейдёт не по тому адресу и отформатирует винчестер, а ARM ещё и в другой режим переключится.
                            Ответить

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