Visual C++ 6.0 — возможная потеря данных при преобразовании (предупреждение C4244)

Я использую довольно старый компилятор, и я считаю, что компилятор сделал небольшую ошибку в диагностике предупреждений.

    typedef unsigned char uint8_t;          // 8-bit byte
    typedef unsigned int uint32_t;          // 32-bit word (change to "long" for 16-bit machines)
    
    typedef struct _sha256_ctx_t
    {
        uint8_t             data[64];
        uint32_t            data_len;
        unsigned __int64    bit_len;        // unsigned long long
        uint32_t            state[8];
    } sha256_ctx_t;


void crypto_sha256_final(sha256_ctx_t *ctx, uint8_t *digest)
{
    uint32_t i;

    i = ctx->data_len;

    // Append to the padding the total message's length in bits and transform.
    ctx->bit_len += ctx->data_len * 8;
    ctx->data[63] = ctx->bit_len; // LINE 156 IS HERE!
    ctx->data[62] = ctx->bit_len >> 8;
    ctx->data[61] = ctx->bit_len >> 16;
    ctx->data[60] = ctx->bit_len >> 24;
    ctx->data[59] = ctx->bit_len >> 32;
    ctx->data[58] = ctx->bit_len >> 40;
    ctx->data[57] = ctx->bit_len >> 48;
    ctx->data[56] = ctx->bit_len >> 56; // LINE 163 IS HERE!

    local_sha256_transform(ctx, ctx->data);

    // Since this implementation uses little endian byte ordering and SHA uses big endian,
    // reverse all the bytes when copying the final state to the output digest.
    for (i = 0; i < 4; ++i) {
        digest[i]      = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
        digest[i + 4]  = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
        digest[i + 8]  = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
        digest[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
        digest[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
        digest[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
        digest[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
        digest[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
    }
}

Этот код приводит к этой ошибке (от строк 156 до 163):

SHA256.cpp(156) : warning C4244: '=' : conversion from 'unsigned __int64' to 'unsigned char', possible loss of data

Я предполагаю, что этот старый компилятор не понимает, что добавление его с 0xFF сужает результат до байта. У кого-нибудь есть предложения о том, как обойти ложное предупреждение?

Исходный источник кода: https://programmer.group/61737ba233df9.html

Можете ли вы уточнить, какая именно строка в показанном коде «добавляет его с 0xFF»?

Sam Varshavchik 11.05.2022 18:18

Конечно, я добавил это для вас.

matead 11.05.2022 18:22

64-битное число не поместится в 8-битное без потери данных. Это не ложное предупреждение.

2pichar 11.05.2022 18:23
Почему вы используете этот древний, полный ошибок, неподдерживаемый компилятор? Сделайте себе одолжение, бросьте его на обочину и используйте современный компилятор.
Konrad Rudolph 11.05.2022 18:23

Ну да, похоже компилятор этого не понимает, вот и все.

Sam Varshavchik 11.05.2022 18:24

Любые предложения о том, как это исправить? У меня есть свои причины, по которым мне нужно использовать именно этот компилятор.

matead 11.05.2022 18:28

— Честно говоря, исправление заключается в использовании минимально работающего компилятора. Если у вас действительно есть веские причины использовать безнадежно сломанный, все, что мы можем сделать, это пожелать вам удачи. Но если бы вы рассказали нам больше о своих причинах, мы потенциально могли бы предложить альтернативы.

Konrad Rudolph 11.05.2022 18:29

простое решение - разыграть ctx->data[60] = uint8_t(ctx->bit_len >> 24);. Но настоящее решение — использовать современный компилятор и, хорошую криптографическую библиотеку. Современные библиотеки используют SIMD и будут в десятки или сотни раз быстрее, чем эта.

phuclv 11.05.2022 18:34

Спасибо за предложение по актерскому составу. Это решило это.

matead 11.05.2022 18:40

Не размещайте решения в теле вопроса. Сделайте отдельный ответ, пожалуйста. Это правила сайта.

JHBonarius 11.05.2022 18:57

@matead, возможно, вы захотите проверить OpenWatcom, это компилятор с открытым исходным кодом, который поддерживает почти все системы VC++6 и, по крайней мере, все еще «поддерживается»

Mgetz 12.05.2022 14:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
56
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В этом случае с компилятором все в порядке.

ctx->data[63] = ctx->bit_len; // LINE 156 IS HERE!
ctx->data[62] = ctx->bit_len >> 8;
ctx->data[61] = ctx->bit_len >> 16;
ctx->data[60] = ctx->bit_len >> 24;
ctx->data[59] = ctx->bit_len >> 32;
ctx->data[58] = ctx->bit_len >> 40;
ctx->data[57] = ctx->bit_len >> 48;
ctx->data[56] = ctx->bit_len >> 56; // LINE 163 IS HERE!

ctx->bit_len — это 64-битный тип, поэтому очевидно, что сохранение его в uint8_t не работает. В этих строках нет маскировки с помощью 0xFF, как в digest[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;. Единственный случай, когда отсутствует анализ, это ctx->data[56] = ctx->bit_len >> 56, потому что результат соответствует uint8_t. Чтобы получить LSB, вам нужно сделать явное приведение, чтобы компилятор знал, что вы делаете.

ctx->data[62] = uint8_t(ctx->bit_len >> 8);

При этом нет необходимости копировать вручную, просто используйте memcpy и ntohll. Код не очень хорош, а использование древнего компилятора еще хуже. В настоящее время существует множество хороших криптографических библиотек, которые используют правильный SIMD и многопоточность, такие как OpenSSL.

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

Попробуйте это лекарство: приведите назначенное выражение к char.

Другие вопросы по теме