У програмуванні перевірка меж () — це будь-який метод виявлення того, чи перебуває змінна в певних межах, перш ніж її буде використано. Зазвичай вона використовується для перевірки того, що число вміщується у заданий тип (перевірка діапазону), або що змінна, яка використовується як індекс масиву, перебуває в межах масиву (перевірка індексу). Невдала перевірка меж зазвичай призводить до генерування певного сигналу винятку.
Оскільки виконання перевірки меж під час кожного використання може забирати багато часу, вона виконується не завжди. Усунення перевірки меж є технікою оптимізації компілятора, яка усуває непотрібні перевірки меж.
Перевірка діапазону
Перевірка діапазону підтверджує, що число перебуває в допустимому для роботи програми діапазоні, наприклад забезпечує, щоб значення, яке має бути присвоєне 16-бітному цілому числу, перебувало в межах можливостей 16-бітного цілого числа (тобто виконується перевірка на циклічне переповнення). Це дещо відрізняється від перевірки типів, яка підтверджує, що тип даних відповідає системі типів програми. Інші перевірки діапазону можуть бути більш обмежувальними; наприклад, змінна для зберігання номера місяця календаря може бути оголошена так, щоб приймати лише діапазон від 1 до 12.
Приклад мовою Python: def set_month(month: int): if month < 1 or month > 12: raise ValueError("The month must be between 1 and 12")
Перевірка індексу
Перевірка індексу означає, що у всіх виразах, які індексують масив, значення індексу перевіряється на відповідність межам масиву (які були встановлені під час визначення масиву), і якщо індекс виходить за межі, подальше виконання призупиняється за допомогою певної помилки. Оскільки читання або, особливо, запис значення за межами масиву може призвести до неправильної роботи чи аварійного завершення програми або створити вразливості безпеки (див. переповнення буфера), перевірка індексів є частиною багатьох мов програмування високого рівня.
До ранніх компільованих мов програмування з можливістю перевірки індексів належали ALGOL 60, ALGOL 68 і Pascal, а також інтерпретовані мови програмування, такі як BASIC.
Багато мов програмування, наприклад C, ніколи не виконують автоматичну перевірку меж для підвищення швидкості. Однак через це багато помилок на одиницю та переповнень буфера залишаються невиявленими. Багато програмістів вважають, що ці мови надто багато жертвують заради швидкого виконання. У своїй лекції з нагоди отримання премії Тюрінга 1980 року Тоні Гоар описав свій досвід проєктування ALGOL 60, мови, яка включала перевірку меж, сказавши:
До основних мов, які забезпечують перевірку під час виконання, належать Ada, C#, Haskell, Java, JavaScript, Lisp, PHP, Python, Ruby, Rust та Visual Basic. Мови D та OCaml мають перевірку меж під час виконання, яку можна вмикати або вимикати перемикачем компілятора. У C++ перевірка під час виконання не є частиною самої мови, але є частиною STL і вмикається перемикачем компілятора (_GLIBCXX_DEBUG=1 або _LIBCPP_DEBUG=1). C# також підтримує небезпечні області (unsafe regions): ділянки коду, у яких, серед іншого, можна тимчасово призупинити перевірку меж для підвищення ефективності. Це корисно для прискорення невеликих критичних за часом вузьких місць без принесення в жертву безпеки всієї програми.
Апаратна перевірка меж
Додаткова безпека, яку забезпечує перевірка меж, неминуче потребує процесорного часу, якщо перевірка виконується програмно; однак, якщо перевірки можна виконувати апаратно, безпеку можна забезпечити «безкоштовно», без витрат часу під час виконання. Ранньою системою з апаратною перевіркою меж була серія мейнфреймів ICL 2900, представлена 1974 року. Комп'ютер VAX має інструкцію асемблера INDEX для перевірки індексу масиву, яка приймає шість операндів, кожен із яких може використовувати будь-який режим адресації VAX. B6500 та подібні комп'ютери Burroughs виконували перевірку меж апаратно, незалежно від того, якою мовою програмування було скомпільовано машинний код. Обмежена кількість пізніших ЦП має спеціалізовані інструкції для перевірки меж, наприклад інструкцію CHK2 у серії Motorola 68000.
Дослідження методів використання вбудованого блока керування віртуальною пам'яттю x86 для забезпечення безпеки доступу до масивів і буферів ведуться щонайменше з 2005 року. У 2015 році Intel представила свої розширення Intel MPX в архітектурі процесорів Skylake, які зберігають межі в регістрі ЦП та таблиці в пам'яті. Станом на початок 2017 року щонайменше GCC підтримує розширення MPX.
Див. також Знаходження помилки під час виконання Динамічний аналіз коду Статичний аналіз коду
Примітки
Посилання “On The Advantages Of Tagged Architecture”, IEEE Transactions On Computers, Volume C-22, Number 7, July, 1973. “The Emperor’s Old Clothes ”, The 1980 ACM Turing Award Lecture, CACM volume 24 number 2, February 1981, pp 75–83. “Bcc: Runtime checking for C programs”, Samuel C. Kendall, Proceedings of the USENIX Summer 1983 Conference. “Bounds Checking for C”, Richard Jones and Paul Kelly, Imperial College, July 1995. “ClearPath Enterprise Servers MCP Security Overview”, Unisys, April 2006. “Secure Virtual Architecture: A Safe Execution Environment for Commodity Operating Systems”, John Criswell, Andrew Lenharth, Dinakar Dhurjati, Vikram Adve, SOSP'07 21st ACM Symposium on Operating Systems Principles, 2007. “Fail-Safe C”, Yutaka Oiwa. Implementation of the Memory-safe Full ANSI-C Compiler. ACM SIGPLAN Conference on Programing Language Design and Implementations (PLDI2009), June 2009. “address-sanitizer”, Timur Iskhodzhanov, Alexander Potapenko, Alexey Samsonov, Kostya Serebryany, Evgeniy Stepanov, Dmitriy Vyukov, LLVM Dev Meeting, November 18, 2011. Safe C Library of Bounded APIs
Safe C API—Concise solution of buffer overflow, The OWASP Foundation, OWASP AppSec, Beijing 2011 The GNU C++ Library Manual Macros libc++ 11.0 documentation Debug Mode