Русский
Русский
English
Статистика
Реклама

Область видимости

С безопасность для новичков

05.03.2021 18:07:04 | Автор: admin

Привет, хабровчане. Для будущих студентов курса "C++ Developer. Professional" Александр Колесников подготовил статью.

Приглашаем также посмотреть открытый вебинар на тему
Области видимости и невидимости. За 1,5 часа участники вместе с экспертом успеют реализовать класс общего назначения и запустить несколько unit-тестов с использованием googletest. Присоединяйтесь.


В статье на примерах будет рассмотрено, почему приложения на языке программирования С++ стоит разрабатывать с особым вниманием.

Сегодня язык программирования С++ существует в нескольких параллельных реальностях: C++98, C++11, C++14, C++17, C++20. Существует как минимум один источник, где можно немного разобраться со всем этим набором мультивселенных. Однако, когда дело дойдет до написания кода использования stackOverflow, вопрос а точно эта строка написана безопасно", будет мучать разработчика из релиза в релиз. Кстати, на момент написания статьи готовится новый стандарт С++23 =).

Откуда проблемы

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

Самые распространенные проблемы, с которыми может столкнуться новичок:

  • неверное объявление типов данных;

  • неверное использование выражений;

  • неправильная обработка целочисленных данных;

  • неправильная работа с контейнерами;

  • неправильная работа со строками;

  • неправильная работа с памятью;

  • неверная обработка exception;

  • пренебрежение ограничениями OOP;

  • состояния гонки при обработке ресурсов мультипоточным приложением;

  • прочие проблемы, о которых мало, где сказано.

Похоже, что если вчитаться в список ограничений, то можно подумать, что С++ это сплошное нельзя и вроде проканает, запустится и будет работать. Безусловно, можно сконцентрироваться на алгоритме и не обращать внимание на все описанные выше проблемы, но, к сожалению, большое количество CVE, которые заводят именно на приложения, написанные на С++, зашкаливает.

Разберем несколько примеров.

String Format

void check_password(const char *user) {  int ret;  //  static const char format[] = "%s wrong pass.\n";  size_t messageLength = strlen(user) + sizeof(msg_format);  char *data = (char *)malloc(messageLength); // <- так же не очень безопасный вариант  if (data == NULL) {    //Код для ошибки  }  ret = snprintf(data, messageLength, format, user);  if (ret < 0) {     //Код для ошибки  } else if (ret >= messageLength) {     //Последний шанс обработать некорректные данные  }  syslog(LOG_INFO, msg);  free(msg);}

В чем проблема? Данные, которые используются для создания строки, контролируются пользователем. Передача других спец символов (%n, %x) и использование строк больших размеров может вывести из строя приложение.

Integer overflow

Данная проблема головная боль любого ПО, которое работает с накапливаемыми данными. Какого размера переменные использовать, чтобы оптимально хранить данные и одновременно сделать запас для приложения, если если оно будет использоваться месяцами без перезапуска? В некоторых случаях ответить однозначно на этот вопрос нельзя, поэтому программист, ориентируясь на собственный опыт, волевым решением пишет uint16_t. Но данных оказывается больше 65,535 и тут случается чудо значение переменной становится равно нулю и отсчет идёт заново. Пример кода:

...user->nameLength = getUserNameLength(&user->name) ;user->newDbCellLen = malloc(user->nameLength * sizeof(uint8_t))...

Одна строка и один выстрел в голову всему приложению. Теперь пользователь может спокойно выделять столько памяти, сколько ему нужно. При этом приложение продолжит какое-то время работать. Исправить можно с помощью простой функции:

...int16_t checkLen(uint16_t firstNumber, uint16_t secondNumber){    uint16_t resultLength;    if (UINT_MAX - firstNumber < secondNumber)     {        //ошибка        return -1;    }    else    {        resultLength = firstNumber + secondNumber;    }    return resultLength;}

Преобразование типов

Если вас не пугают сложности и вы все-таки хотите развиваться как программист С++, то скорее всего к вам в руки попадет код, который разрабатывался Когда динозавры под стол пешком ходили и в нем будет много кода, аналогичному приведенному ниже:

...unsigned int number = (unsigned int)ptr;number = (number & 0x7fffff) | (flag << 23);ptr = (char *)number;...

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

Выводы

Как видно из примеров в статье, С++ это язык, в котором нужно внимательно относиться к кажущимся мелочам, начиная от форматов данных и заканчивая типами переменных. Где брать примеры? Что делать с уязвимостями? К сожалению, универсального ответа нет, но можно постоянно работать и накапливать знания о языке и его особенностях. Начать можно здесь или здесь. Так же нужно использовать плагины и приложения, которые позволяют анализировать код на этапе сборки. Можно в этом случае ориентироваться на продукты вроде этого или этого.


Узнать подробнее о курсе "C++ Developer. Professional".

Смотреть открытый вебинар на тему Области видимости и невидимости.

Подробнее..

Перевод JavaScript область видимости простыми словами

01.09.2020 12:04:25 | Автор: admin


Доброго времени суток, друзья!

Область видимости важная концепция, определяющая доступность переменных. Данная концепция лежит в основе замыканий, разделяя переменные на глобальные и локальные.

В этой статье я постараюсь простыми словами объяснить, что такое область видимости в JavaScript.

1. Область видимости


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

Допустим, мы определили переменную:

const message = 'Hello'console.log(message) // 'Hello'

Мы легко можем вывести ее значение в консоль. Это понятно.

Теперь поместим объявление переменной message в блок if:

if (true) {    const message = 'Hello'}console.log(message) // ReferenceError: message is not defined

На этот раз при попытке доступа к переменной выбрасывается исключение ReferenceError: message is not defined.

Почему это произошло?

Потому что блок if создал область видимости для переменной message. И message доступна только внутри этой области.



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

Итак, область видимости это зона доступности переменных.

2. Блочная область видимости


Блок кода в JavaScript определяет область видимости переменных, объявленных с помощью ключевых слов const и let:

if (true) {    // область видимости блока if    const message = 'Hello'    console.log(message) // 'Hello'}console.log(message) // ReferenceError

Первый console.log() благополучно выводит значение переменной message в консоль, поскольку доступ к этой переменной осуществляется в той области видимости, в которой она определена.

Однако вызов второго console.log() приводит к возникновению ошибки, поскольку переменная message недоступна во внешней по отношению к ней области видимости: в текущем контексте message не существует.

В инструкциях if, for, while также создается блочная область видимости.

Например:

for (const color of ['green', 'red', 'blue']) {    // область видимости блока for    const message = 'Hi'    console.log(color) // 'green', 'red', 'blue'    console.log(message) // 'Hi', 'Hi', 'Hi'}console.log(color) // ReferenceErrorconsole.log(message) // ReferenceError

Переменные color и message существуют только внутри блока for.

Тоже самое справедливо для инструкции while:

while (/* условие */) {    // область видимости блока while    const message = 'Hi'    console.log(message) // 'Hi'}console.log(message) // ReferenceError

message, определенная в while, доступна только внутри данного цикла.

В JavaScript вы можете создавать самостоятельные блоки кода. Они также определяют собственную область видимости:

{    const message = 'Hi'    console.log(message) // 'Hi'}console.log(message) // ReferenceError

2.1. var не имеет блочной области видимости


Как мы видели в предыдущих примерах, блок кода создает область видимости для переменных, орбъявленных с помощью ключевых слов const и let. Однако это не работает для переменных, объявленных с помощью ключевого слова var.

Рассмотрим пример:

if (true) {    // область видимости блока if    var count = 0    console.log(count) // 0}console.log(count) // 0

Переменная count, как и ожидалось, доступна внутри блока if. Однако, она доступна и за пределами данного блока!

Дело в том, что блок кода не создает области видимости для переменных, объявленных с помощью ключевого слова var. Но это делает функция.

3. Область видимости функции


Функции в JavaScript создают область видимости для всех переменных, независимо от того, с помощью какого ключевого слова они объявлены (var, const или let).

Например:

function run() {    // область видимости функции run()    var message = 'Беги, Форрест, беги!'    console.log(message)}run() // 'Беги, Форрест, беги!'console.log(message) // ReferenceError

Функция run() создает область видимости. Переменная message доступна внутри функции, но недоступна снаружи.

Аналогичным образом функция создает область видимости для переменных, объявленных с помощью const и let, и даже для других функций и функциональных выражений:

function run() {    // область видимости функции run()    const two = 2    let one = 1    function run2() {}    var run3 = () => {}    console.log(two)    console.log(one)    console.log(run2)    console.log(run3)}run() // 2 1  run2() {} () => {}console.log(two) // ReferenceErrorconsole.log(one) // ReferenceErrorconsole.log(run2) // ReferenceErrorconsole.log(run3) // ReferenceError

4. Область видимости модуля


Модули ES6 также создают область видимости для переменных, функций и классов.

Модуль circle создает константу pi (для внутреннего использования):

// область видимости модуля circleconst pi = 3.14console.log(pi) // 3.14// использование pi

Переменная pi объявляется внутри модуля circle и не экспортируется из него.

Затем модуль circle импортируется:

import './circle'console.log(pi) // ReferenceError

Переменная pi недоступна за пределами модуля circle (до тех пор, пока она не будет экспортирована с помощью export).

Модульная область видимости инкапсулирует модули. Это означает, что частные переменные (которые не экспортируются) используются для собственных нужд модуля и защищены от доступа извне.

Таким образом, можно сказать, что область видимости это механизм инкапсуляции для блоков кода, функций и модулей.

5. Области видимости могут быть вложенными


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

В следующем примере функция run() создает область видимости, а внутри нее блок if создает еще одну область:

function run() {    // область видимости функции run()    const message = 'Беги, Форрест, беги!'    if (true) {        // область видимости блока if        const friend = 'Бубба'        console.log(message) // 'Беги, Форрест, беги!'    }    console.log(friend) // ReferenceError}run()

Область видимости блока if вложена в область видимости функции run().

Область видимости, находящаяся внутри другой области, называется внутренней областью видимости. В приведенном примере это область видимости блока if.

Область видимости, содержащая другую область, называется внешней областью видимости. В приведенном примере это область видимости фукнции run().



Что насчет доступности переменных? Нужно запомнить простое правило:

Переменные из внешней области видимости доступны во внутренней области.

Поэтому переменная message доступна внутри блока if.

6. Глобальная область видимости


Глобальная область видимости является самой внешней областью. Она доступна для любой внутренней или локальной области видимости. В браузере глобальной является область видимости, создаваемая при загрузке JavaScript-файла, указанного в атрибуте src тега script:

<script src="script.js">


// script.js
// глобальная область видимости
let counter = 1

Переменные, объявленные в глобальной области видимости являются глобальными переменными. Они доступны в любой другой области.

Глобальная область видимости это механизм, который позволяет среде выполнения JavaScript-кода (браузеру, Node.js) предоставлять приложениям хостовые (т.е. принадлежащие среде) объекты как глобальные переменные.

Например, window и document являются глобальными переменными (объектами), предоставляемыми браузером. В Node.js такой переменной является, например, объект process.

7. Лексическая область видимости


Определим две функции, одна из которых вложена в другую:

function outer() {    // область видимости функции outer()    let v = 'Я из области видимости функции outer()!'    function inner() {        // область видимости функции inner()        console.log(v) // 'Я из области видимости функции outer()!'    }    return inner}const f = outer()f()

Взгляните на последнюю строку: функция inner() вызывается за пределами области видимости функции outer(). Как JavaScript понимает, что значение, выводимое в консоль в функции inner(), принадлежит переменной v, объявленной в фукнции outer()?

Ответ: благодаря лексической области видимости.

JavaScript реализует механизм под названием лексическая или статическая область видимости. Лексическая область видимости означает, что доступность переменных определяется статически положением данных переменных внутри области видимости вложенной функции: переменные из области видимости внешней функции доступны в области видимости вложенной функции.

Формальное определение лексической области гласит следующее:

Лексическая область видимости состоит из внешних областей видимости, определенных статически, т.е. из внешних областей, зафиксированных использованием переменных из этих областей во внутренних функциях.

В приведенном примере лексическая область видимости функции inner() состоит из области видимости функции outer().

Более того, inner() это замыкание, поскольку в ней используется значение переменной из лексической области видимости.

8. Изоляция переменных


Очевидно, что область видимости изолирует переменные. Благодаря этому разные области видимости могут содержать переменные с одинаковыми именами.

Вы можете использовать переменные count, index, current, value и т.д. в разных областях без угрозы возникновения коллизий (конфликтов имен).

Например:

function foo() {    // область видимости функции foo()    let count = 1    console.log(count) // 1}function bar() {    // область видимости функции bar()    let count = 2    console.log(count) // 2}foo()bar()

Заключение


Область видимости определяет доступность переменных. Переменная, объявленная в текущей области видимости, доступна только внутри нее.

В JavaScript области видимости создаются блоками, функциями и модулями.

Переменные, объявленные с помощью ключевых слова const и let могут иметь блочную, функциональную или модульную область видимости, а переменные, объявленные с помощью ключевого слова var, не имеют блочной области видимости.

Области видимости могут быть вложенными. Переменные, объявленные во внешней области видимости, доступны во внутренней области.

Лексическая область видимости состоит из внешних областей, определенных статически. Любая функция, независимо от места выполнения, имеет доступ к переменным из ее лексической области видимости (в этом заключается суть замыканий).

Надеюсь статья была вам полезной. Благодарю за внимание.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru