Anatoly Vorobey (avva) wrote,
Anatoly Vorobey
avva

Category:

программистское

(интересно только программистам, знающим C)

Майкрософтовский strlen(), оказывается, не проверяет, не передали ли ему случаем NULL, а по-простому читает то, что по переданному адресу находится, и падает кверху лапками.

Если майкрософтовскому printf'у передать NULL в качестве аргумента, соответствующего %s в строке формата, он это проверит и выдаст "(null)".

Однако у Glib'а (библиотека низкого уровня, лежащая в основе GTK, в основном использующаяся на юниксах, но по идее поддерживающая и платформу Win32) есть внутри своя имплементация printf'а (а точнее, vasnprintf()'а, чтобы покрыть все возможные случаи). Она не делает полностью всю работу printf'а, а всего лишь обрабатывает строку формата и аргументы и строит отдельные более простые вызовы snprintf/sprintf (хотя бы sprintf уже должен быть везде) для каждого аргумента, размещая их по очереди в буфере возврата. Glib использует эту имплементацию в том случае, когда у платформы, на которой её строят, нет своего достаточно хорошего и поддерживающего всё, что нужно, printf'а. Win32 - одна из таких платформ.

Если этому внутреннему Glib'овскому printf'у передать NULL в качестве аргумента, соответствующего %s в форматной строке, то он в определённый момент вызовет strlen() на этот аргумент, чтобы узнать длину строки аргумента - для того, чтобы создать буфер достаточной длины. Увы, авторам этого printf'а не пришло в голову, что strlen на какой-то платформе может упасть, если передать ему NULL. Поэтому они это не проверяют, и в результате, если вызвать что-то вроде: g_printf("foo: %s\n", NULL), то программа упадёт.

Это всё я обнаружил, пытаясь построить и заставить что-то делать ЖЖ-клиент LogJam под Windows XP.

Интересно, кто виноват? Аппликация, передающая какой-либо версии printf'а аргумент NULL для подстановки к %s? Имплементация printf'а, вызывающая strlen(), не проверяя аргумент на ==NULL? Имплементация strlen(), идущая сразу по адресу аргумента, не проверяя на NULL?

P.S. Проверил strlen() на юниксах (glibc). Он тоже, оказывается, не проверяет на NULL. Но там тот же баг не проявлялся потому, что GLib использует системный printf, а не свой, а системный это дело проверяет.
Subscribe

Recent Posts from This Journal

  • теория вероятности и тревожность

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

  • поддавки

    Понравилась шахматная(?) задачка от Евгения Поникарова. Автор задачи John Beasley. Белые начинают и выигрывают в поддавки. Напомню правила игры в…

  • спускались в шахты с нелитературными целями

    Лет шесть или семь не видел имя Дивова (российский фантаст) и почти забыл о его существовании. А тут. А тут, оказывается, такое движение, такая…

  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 49 comments
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →

Recent Posts from This Journal

  • теория вероятности и тревожность

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

  • поддавки

    Понравилась шахматная(?) задачка от Евгения Поникарова. Автор задачи John Beasley. Белые начинают и выигрывают в поддавки. Напомню правила игры в…

  • спускались в шахты с нелитературными целями

    Лет шесть или семь не видел имя Дивова (российский фантаст) и почти забыл о его существовании. А тут. А тут, оказывается, такое движение, такая…