что такое стандартный паттерн миринда
Проект Miranda NG получает приз «дикие указатели» (часть первая)
О проверке Miranda NG
Проект Miranda NG — это преемник популярного мультипротокольного IM-клиента для Windows, Miranda IM.
Вообще, изначально я не собирался проверять Miranda NG. Нам просто нужно несколько активно развивающихся проектов, чтобы тестировать новую фичу PVS-Studio. Можно использовать специальную базу, в которой хранится информация о сообщениях, которые не надо выдавать. Подробнее про это рассказано здесь. Идея в следующем. Иногда сложно внедрить статический анализ в большой проект, так как выдаётся слишком много предупреждений и непонятно, что с ними делать и кому это поручить. Но хочется начать получать пользу от статического анализа уже сейчас. Поэтому для начала можно скрыть все предупреждения и рассматривать только новые, которые появляются в процессе написания нового кода или рефакторинга. А уж потом, когда есть силы и желание, можно потихоньку править ошибки в старом коде.
Одним из активно развивающихся проектов оказался Miranda NG. Но когда я посмотрел, что выдал PVS-Studio при первом запуске, я понял, что у меня есть материал на новую статью.
Итак, давайте посмотрим, что нашел статический анализатор кода PVS-Studio в исходных кодах Miranda NG.
Для проверки Miranda NG из репозитория был взят Trunk. Хочу отметить, что я смотрел отчёт анализатора весьма поверхностно и наверняка многое упустил. Я пробежался только по диагностикам общего назначения 1 и 2-ого уровня. Третий уровень я даже не стал смотреть. Мне и первых двух хватило с избытком.
Часть первая. Указатели и работа с памятью
Разыменовывание нулевого указателя
Предупреждение PVS-Studio: V522 Dereferencing of the null pointer ‘cont’ might take place. EmLanProto mlan.cpp 342
Здесь все просто. Раз указатель равен NULL, то давайте его разыменуем и посмотрим, что весёлого из этого получится.
В начале используем указатель, потом проверяем
Таких ошибок в Miranda NG тьма тьмущая, как и в любом приложении. Обычно такой код работает, так как в функцию приходит ненулевой указатель. А вот если нулевой, то функции к этому не готовы.
Предупреждение PVS-Studio: V595 The ‘dat’ pointer was utilized before it was verified against nullptr. Check lines: 428, 430. TabSRMM buttonsbar.cpp 428
Если в функцию BB_InitDlgButtons() передать NULL, то проверка будет сделана слишком поздно. Анализатор выдал на код проекта Miranda NG ещё 164 таких предупреждения. Нет смысла приводить их в статье. Вот все они списком: MirandaNG-595.txt.
Потенциально неинициализированный указатель
Предупреждение PVS-Studio: V614 Potentially uninitialized pointer ‘url’ used. IEView ieview.cpp 1117
Если условие if (SUCCEEDED(. )) не выполняется, то переменная ‘url’ остаётся неинициализированной и функция должна вернуть непонятно что. Но не всё так просто. Код содержит ещё одну ошибку. Неправильно поставлена закрывающаяся скобка. В результате макрос SUCCEEDED применяется к выражению типа ‘bool’, что не имеет смысла.
Второй баг компенсирует первый. Посмотрим, что такое макрос SUCCEEDED:
Выражение типа ‘bool’ равно 0 или 1. В свою очередь, 0 или 1 всегда >= 0. Получается, что макрос SUCCEEDED всегда возвращает истину и переменная ‘url’ всегда инициализируется.
Только что мы воочию увидели красивый пример, когда один баг компенсирует другой. Если исправить условие, проявит баг с неинициализированной переменной.
Если иcправить 2 ошибки, то код будет выглядеть так:
Анализатор подозревает неладное ещё в 20 местах. Вот они: MirandaNG-614.txt.
Путаница между размером массива и количеством элементов
Количество элементов в массиве и размер массива в байтах — две разные сущности. Однако, если быть недостаточно внимательным, их вполне можно перепутать. Проект Miranda NG демонстрирует множество способов, как может выглядеть такая путаница.
Больше всего вреда нанёс макрос SIZEOF:
Этот макрос вычисляет количество элементов в массиве. Но, видимо, кто-то из программистов считает, что это аналог оператора sizeof(). Правда, не понятно, зачем он тогда использует макрос, а не стандартный sizeof(). Так что есть и другой вариант — кто-то не знает, как использовать функцию memcpy().
Предупреждение PVS-Studio: V512 A call of the ‘memcpy’ function will lead to underflow of the buffer ‘s_list’. Sessions utils.cpp 288
Функция memcpy() скопирует только часть массива, так как третий аргумент задаёт размер массива в байтах.
Точно так же неправильно макрос SIZEOF() используется ещё в 8 местах: MirandaNG-512-1.txt.
Следующая беда. Часто программисты забывают поправить вызовы memset()/memcpy() когда внедряют в программу Unicode:
А вот пример частичного копирования строки:
Предупреждение PVS-Studio: V512 A call of the ‘memcpy’ function will lead to underflow of the buffer ‘L«mailto:»’. TabSRMM msgdialog.cpp 2085
Будет скопирована только часть строки. Каждый символ строки занимает 2 байта. Значит скопировать надо 14 байт, а не 7.
Предупреждение PVS_Studio: V512 A call of the ‘memset’ function will lead to underflow of the buffer ‘logfonts’. TabSRMM msglog.cpp 134
Кто-то поспешил и смешал в кучу размер объекта и их количество. Прибавлять двойку нужно до умножения. Корректный код:
В следующем примере хотели, как лучше, использовали sizeof(), но вновь запутались с размерами. Получили значение больше, чем нужно.
Предупреждение PVS-Studio: V620 It’s unusual that the expression of sizeof(T)*N kind is being summed with the pointer to T type. Scriver input.cpp 387
Переменная ‘tr.lpstrText’ указывает на строку, состоящую из символов типа wchat_t. Если хочется пропустить 7 символов, то нужно просто прибавить 7. Не нужно умножать на sizeof(wchar_t).
Такая же ошибка здесь: ctrl_edit.cpp 351
К сожалению, это ещё не конец. Ещё можно ошибиться так:
Предупреждение PVS-Studio: V641 The size of the allocated memory buffer is not a multiple of the element size. KeyboardNotify options.cpp 718
Забыли умножить на sizeof(TCHAR). В этом же файле можно увидеть ещё 2 ошибки в строках 819 и 1076.
И последний фрагмент кода на тему количества элементов:
Предупреждения PVS-Studio: V635 Consider inspecting the expression. The length should probably be multiplied by the sizeof(wchar_t). KeyboardNotify main.cpp 543
Ещё стоит дописать умножение на sizeof(TCHAR) здесь: options.cpp 1177, options.cpp 1204.
С размерами разобрались, перейдём к другим способам выстрелить себе в ногу указателем.
Выход за границу массива
V512 A call of the ‘strcat’ function will lead to overflow of the buffer ‘fn’. NimContact files.cpp 290
Строка «_timer» не влезает в массив ‘fn’. Хотя в строке всего 6 символов, нужно не забывать про терминальный 0. Теоретически здесь имеет место неопределённое поведение. На практике получится, что будет задет массив ‘tmp’. В нулевой элемент массива ‘tmp’ будет записан ‘0’.
Следующий пример ещё печальней. Здесь испортится HANDLE какой-то иконки:
Предупреждение PVS-Studio: V512 A call of the ‘strcpy’ function will lead to overflow of the buffer ‘cap.caps’. New_GPG main.cpp 2246
Вновь не учтён терминальный 0. Возможно, здесь уместнее было бы воспользоваться функцией memcpy().
Великая и ужасная функция strncat()
Многие слышали про опасность функции strcat() и используют на их взгляд более безопасную strncat(). Вот только редко кто умеет обращаться с этой функцией правильно. Она намного опаснее, чем может показаться. Дело в том, что третий аргумент задаёт не максимальную длину буфера, а сколько в буфере осталось свободного места.
Вот такой код совершенно некорректен:
Предупреждение PVS-Studio: V645 The ‘strncat’ function call could lead to the ‘buff’ buffer overflow. The bounds should not contain the size of the buffer, but a number of characters it can hold. Miranda fontoptions.cpp 162
Если, ‘buff’ занят на половину, то такой код не обратит на это внимание и позволит добавить ещё 1000 символов. И таким образом произойдет выход за границу массива. Причем очень существенный. С таким же успехом можно было просто писать strcat().
В Miranda NG есть ещё 48 мест где так неправильно используется strncat(). Вот они: MirandaNG-645-1.txt.
Кстати, эти места в коде можно рассматривать как потенциальные уязвимости.
В оправдание программистов из Miranda NG, стоит отметить, что некоторые всё таки читали описание функции strncat(). Они пишут так:
Предупреждение PVS-Studio: V645 The ‘strncat’ function call could lead to the ‘filename’ buffer overflow. The bounds should not contain the size of the buffer, but a number of characters it can hold. GG filetransfer.cpp 273
К сожалению, это опять неправильно. По крайней мере так можно испортить 1 байт за пределами массива. И я думаю, вы уже догадались, что причина в злосчастном терминальном нуле. Он не учтён.
Поясним эту ошибку на простом примере:
В буфере уже нет места для новых символов. В нём находится 4 символа и терминальный ноль. Выражение «5 — strlen(buf)» равно 1. Функция strncpy() скопирует символ «E» в последний элемент массива ‘buf’. Терминальный 0 будет записан уже за пределами буфера.
Остальные 34 места кода собраны здесь: MirandaNG-645-2.txt.
Эротика с использованием new[] и delete
Кто-то систематически забывает писать квадратные скобки для оператора delete:
Предупреждение PVS-Studio: V611 The memory was allocated using ‘new T[]’ operator but was released using the ‘delete’ operator. Consider inspecting this code. It’s probably better to use ‘delete [] workingDir;’. IEView ieview_main.cpp 68
Впрочем, такие ошибки часто обходятся без видимых последствии. Именно поэтому я отнёс их к разделу «эротика». Более жесткое зрелище ожидает ниже.
Разврат с использованием new, malloc, delete и free
Путаются способы выделения и освобождения памяти:
Предупреждение PVS-Studio: V611 The memory was allocated using ‘new’ operator but was released using the ‘free’ function. Consider inspecting operation logics behind the ‘piWidths’ variable. MirandaG15 clcdlabel.cpp 209
Бессмысленные проверки
В случае нехватки памяти обыкновенный оператор ‘new’ генерирует исключение. Поэтому нет смысла проверять указатель, который вернул оператор ‘new’ на равенство нулю.
Обычно лишняя проверка безобидна. Однако, иногда встречается вот такой код:
Предупреждение PVS-Studio: V668 There is no sense in testing the ‘ar’ pointer against null, as the memory was allocated using the ‘new’ operator. The exception will be generated in the case of memory allocation error. ICQ icq_avatar.cpp 608
В случае ошибки следует освободить мьютекс. Но этого не произойдёт. В случае ошибки создания объекта события будут развиваться совсем не так, как планирует программист.
Предлагаю разработчикам проверить следующие 83 аналогичных предупреждений анализатора: MirandaNG-668.txt.
Путаница между SIZEOF() и _tcslen()
Предупреждение PVS-Studio: V514 Dividing sizeof a pointer ‘sizeof (dbv.ptszVal)’ by another value. There is a probability of logical error presence. TranslitSwitcher layoutproc.cpp 827
Здесь написано что-то странное. Макрос SIZEOF() применяется к указателю, что не имеет никакого смысла. Есть подозрения, что хотели подсчитать длину строки. Тогда для этого следует использовать функцию _tcslen().
Порча vptr
Предупреждение PVS-Studio: V598 The ‘memset’ function is used to nullify the fields of ‘CBaseCtrl’ class. Virtual method table will be damaged by this. UInfoEx ctrl_base.cpp 77
Программист поленился и для обнуления полей класса воспользовался функцией ZeroMemory(). Он не учёл, что этот класс содержит указатель на таблицу виртуальных методов. В базовом классе многие методы объявлены как виртуальные. Порча указателя на таблицу виртуальных методов приведёт к неопределённому поведению при работе с объектом, инициализированным таким кустарным методом.
Время жизни объектов
Предупреждение PVS-Studio: V506 Pointer to local variable ‘psr’ is stored outside the scope of this variable. Such a pointer will become invalid. Miranda findadd.cpp 777
Объект ‘psr’ перестанет существовать, когда произойдёт выход из else-ветви. Однако, указатель на этот объект был сохранён и будет в дальнейшем использоваться. Пример настоящего «дикого указателя». К чему приведёт работа с ним — неизвестно.
Ещё один аналогичный пример:
Предупреждение PVS-Studio: V507 Pointer to local array ‘str’ is stored outside the scope of this array. Such a pointer will become invalid. Miranda genmenu.cpp 973
Текст распечатывается во временный массив, который тут же уничтожается. Однако, указатель на этот массив будет использован где-то в другой части программы.
Удивительно, как такие программы вообще работают. Ещё 9 мест, где обитают дикие указатели: MirandaNG-506-507.txt.
Мучения 64-битных указателей
Я не изучал 64-битные диагностики. Посмотрел только предупреждения с номером V220. Почти каждое такое предупреждение — самая настоящая ошибка.
Пример некорректного кода с точки зрения 64-битности:
Куда-то нужно передать 64-битный указатель. Для этого, его нужно превратить в тип LPARAM. Однако, вместо этого указатель насильственно превращают в 32-битный тип LONG. И только потом он будет автоматически расширен до LONG_PTR. Эта ошибка пришла из 32-битных времён, когда типы LONG и LPARAM совпадали. Теперь это не так. Будут испорчены старшие 32 бита в 64-битном указателе.
Такие баги неприятны тем, что очень неохотно проявляют себя. Будет везти, пока память выделяется в младших адресах памяти.
Вот ещё 20 мест, где портятся 64-битные указатели: MirandaNG-220.txt.
Неочищенные приватные данные
Предупреждение PVS-Studio: V597 The compiler could delete the ‘memset’ function call, which is used to flush ‘kappa’ buffer. The RtlSecureZeroMemory() function should be used to erase the private data. Cryptlib cast.cpp 293
В Release версии компилятор удалит вызов функции memset(). Почему так, можно узнать из описания диагностики.
Не затрутся приватные данные ещё в 6 местах: MirandaNG-597.txt.
Разное
Есть ещё пара предупреждений анализатора, которые я свалю в одну кучу.
Предупреждение PVS-Studio: V512 A call of the ‘memset’ function will lead to underflow of the buffer ‘Data’. Weather weather_ini.cpp 250
Выражение ‘sizeof(Data)’ возвращает размер указателя, а не WIDATA. Будет обнулена только часть объекта. Правильно будет написать: sizeof(*Data).
Предупреждение PVS-Studio: V713 The pointer ftcd was utilized in the logical expression before it was verified against nullptr in the same logical expression. Sametime files.cpp 423
В условии цикла указатель ‘ftcd’ в начале разыменовывается, а только потом проверяется. Видимо, выражение стоит переписать так:
Заключение
Работа с указателями и памятью — не единственное, из чего состоят программы на Си++. В следующей статье мы рассмотрим другие разновидности ошибок, обнаруженных в Miranda NG. Их поменьше, но всё равно достаточно много.
Эта статья на английском
Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. Miranda NG Project to Get the «Wild Pointers» Award (Part 1).
Что такое стандартный паттерн миринда
Для участия в Акции Участнику необходимо выполнить следующие действия:
Общий срок проведения Акции, включая период выдачи призов Победителям: период с «14» июня 2021г. по «30» октября 2021 г. (включительно).
Период совершения покупки: с «14» июня 2021г. по «29» августа 2021г. (включительно);
Период регистрации Кодов (далее – «Период регистрации Кодов»): с 12 часов 00 минут 00 секунд «14» июня 2021г. по 23 часа 59 минут 59 секунд (включительно) «29» августа 2021г. (по московскому времени).
Период выдачи призов Победителям Акции: с «01» июля 2021г. по «30» октября 2021 г. (включительно)
В Акции участвует следующая продукция в промо-упаковке (промо-этикетка и крышки с Кодами под ними):
Оператор 1: Оператором Акции, то есть юридическим лицом, созданным в соответствии с законодательством Российской Федерации, заключившим договор с Организатором Акции на проведение Акции в его интересах и по его поручению, является ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ «ЛЕТО» (юридический адрес: 127015, Москва г, Новодмитровская Б. ул, дом № 14, строение 4, этаж 2, пом. IV, ком. 4З, ИНН 7715750935, КПП 771501001, ОГРН 1097746128039.
Обязанности Оператора 1: Работа промо сайта https://mirinda.ru, первичный сбор данных Участников Акции, контроль и реализация проведения Акции в целом, включая выдачу Главного приза Победителю Акции, исполнение функции налогового агента.
Оператор 2: Оператором Акции, то есть юридическим лицом, созданным в соответствии с законодательством Российской Федерации, заключившим договор с Организатором Акции на проведение Акции в его интересах и по его поручению, является ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ «ИНТЕРНЕТ-АГЕНТСТВО ДАЛЕЕ» (юридический адрес: 19270, г. Москва, Бутырская, 77, ИНН 7704642617, КПП 770401001, ОГРН 5077746435080.
Оператор 3: Оператором Акции, то есть юридическим лицом, созданным в соответствии с законодательством Российской Федерации, заключившим договор с Организатором Акции на проведение Акции в его интересах и по его поручению, является ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ «АЙ СИ ЭН ИКС» (юридический адрес: 121059, г. Москва, ул. Киевская, д. 7, подъезд 7, этаж 5, помещение литер В, комнаты 40,4, ИНН 7720248752, КПП773001001, ОГРН 1037700169627.
Обязанности Оператора 3: Отправка писем-уведомлений участникам Акции.
Оператор 4: Оператором Акции, то есть юридическим лицом, созданным в соответствии с законодательством Российской Федерации, заключившим договор с Организатором Акции на проведение Акции в его интересах и по его поручению, является ИНДИВИДУАЛЬНЫЙ ПРЕДПРИНИМАТЕЛЬ ГАФАРОВ ВЛАДИСЛАВ КОНСТАНТИНОВИЧ (Юридический адрес: 144009, Московская область, г. Электросталь, ул. Юбилейная, д. 13, кв. 143. ОГРНИП 314505332200012. ИНН 505311232102.
Обязанности Оператора 4: Ответы на вопросы пользователей в Чат-боте Акции. Как я могу зарегистрировать код? Зарегистрировать Код, расположенный под крышкой продукции, можно на Сайте или в Чат-бот ВКонтакте и Telegram путем ввода Кода в соответствующем окне. Где и как я могу получить свой приз?
Призы стоимостью менее 4 000 (четырех тысяч) рублей в виде электронного кода или сертификата отображаются в разделе «Личный кабинет» на Сайте или диалогах Чат-бот ВКонтакте и Telegram. Моментом вручения Приза в виде электронного кода или сертификата признается факт проверки Кода Участника, за который он получил Приз, и этого отображения электронного кода или сертификата в разделе Личный кабинет на Сайте. После чего Участник принимает на себя риск утери кода или сертификата, в том числе, в связи с допуском третьих лиц к Социальной сети.
Для получения Призов стоимостью свыше 4000 (четырех тысяч) рублей Участник, признанный Победителем, в течение 5-и (пяти) календарных дней с момента отображение выигрыша в разделе «Личный кабинет » на Сайте или диалогах в Чат-боте ВКонтакте и Telegram обязан направить на электронный адрес support@mirinda.ru следующую информацию:
Участники Акции должны обеспечить возможность предоставления Оператору подлинников указанных выше документов / материалов для сверки с предоставленными ранее копиями таких документов / материалов.
Нужно ли сохранять чек? Нет Сколько призов я могу получить?
Один Участник Акции за весь период проведения Акции может получить следующее максимальное количество Призов Акции:
Для того, чтобы принять участие в Творческом конкурсе необходимо:
Скорее всего, с твоего аккаунта была замечена повышенная активность, поэтому он был заблокирован для дальнейшего участия в Акции.
Mirinda
555 (автор) |
Всемирно известный напиток Mirinda принадлежит известной марке PepsiCo и имеет ярко выраженный апельсиновый вкус. На какое-то время Mirinda конкурировала с таким известным безалкогольным напитком, как Фанта.
История создания
Mirinda – бренд, созданный в 1958 году в солнечной Испании, где апельсины очень растут просто чудесные. Яркий и сочный вкус апельсина не мог не натолкнуть создателей напитка на производство апельсинового нектара, который освежит в жаркий день.
Разновидности напитка
Под маркой Mirinda выпускаются газированные напитки с самыми разнообразными фруктовыми вкусами. В частности:
• Mirinda апельсин;
• Mirinda лимон;
• Mirinda грейпфрут;
• Mirinda яблоко;
• Mirinda банан;
• Mirinda маракуйя;
• Mirinda виноград;
• Mirinda ананас;
• Mirinda клубника;
• Mirinda малина;
• Mirinda гибискус;
• Mirinda персик.
Упаковка напитка
В разное время напитки Mirinda можно было приобрести в таких упаковках:
• банка 330 мл.;
• пластиковая бутылка 0,6 мл. (классический литраж для компании PepsiCo);
• пластиковая бутылка 1,25 л.;
• пластиковая бутылка 1,75 л.;
• пластиковая бутылка 2,25 л.
Современная Mirinda
В 2008 году компания PepsiCo провела очередной ребрендинг своей продукции, в результате которого изменились логотипы и названия некоторых брендов, в том числе: Pepsi, Mirinda, 7UP, Mountain Dew.
Факты о Mirinda
• Mirinda – основной конкурент производимых компанией Coca-Cola напитков Fanta и Dr Pepper;
• Существует утверждение, что человек, придумавший бренд Mirinda и продавший его позднее компании PepsiCo, в совершенстве владел эсперанто;
• В странах арабского мира из-за особенностей языка, название напитка пишется как Miranda;
• Грейпфрутовый вкус напитка доступен лишь в странах Ближнего Востока;
• Самым популярным вкусом в мире является апельсиновый;
• Mirinda преимущественно продается за пределами Северной Америки;
• Компания PepsiCo на время прекратила раскрутку бренда Mirinda в определенных странах. Однако спустя несколько лет возобновила свою деятельность на некоторых рынках, в частности, в Украине деятельность бренда возобновилась с лета 20013 года;
• В России в разное время продавались четыре варианта напитка: Mirinda Апельсин, Mirinda Лимон, Mirinda Виноград, Mirinda Персик. Сейчас же по стране распространяется только апельсиновый вкус напитка.
• В Израиле был выпущен ограниченный выпуск Mirinda Лимон в бутылке ёмкостью 1,5 литра;
• Mirinda отлично подходит в качестве элемента для безалкогольных и алкогольных коктейлей. В частности, предлагается два коктейля, в которые добавляется напиток Mirinda Лимон. Летом эти коктейли будут особо пользоваться спросом, так как они охлаждают и наполняют энергией.
Первый коктейль
В шейкере смешать 30 мл. Campari, 15 мл. сиропа Monine Bubblegum, 30 мл. джина.
Далее добавить растертые листья мяты и базилика, все составляющие хорошенько встряхнуть.
Подавать в стакане, доверху налитым напитком Mirinda Лимон.
Второй коктейль
В бокале для мартини смешать: 20 мл. воды, 30 мл. ликера Feigling, 30 мл ликера Litchao.
Добавить растертые листья мяты и доверху налить напитком Mirinda Лимон.
Что такое стандартный паттерн миринда
Интересные факты обо всем на свете. Узнавайте что-то новое и делитесь с другими!
Пикабу в мессенджерах
Активные сообщества
Тенденции
Самый сложный выбор
Пикабушники, что предпочитаем-с в 2к19?
Ну хоть морковку положили.
Светящийся попрыгунчик Mirinda.
Все скидки и промокоды в одном месте
Вы там как, готовы к осенним распродажам? Чтобы не пропустить самые интересные и выгодные предложения, подпишитесь на полезный телеграм-канал Пикабу со скидками. Да, Пикабу не только для отдыха и мемов, но и для экономных покупок!
В «Пикабу Скидки» вы найдете актуальные предложения:
• доставки еды (KFC, Delivery Club, «Папа Джонс»);
• книги («Читай-город», «Литрес», Storytel);
• услуги и сервисы («Делимобиль», Boxberry, «Достависта»);
• маркетплейсы и гипермаркеты (Ozon, «Ашан», «Яндекс.Маркет»);
• одежда и обувь (Adidas, ASOS, Tom Tailor)
• бытовая техника и электроника («М.Видео», «Связной», re:Store);
• товары для дома (IKEA, «Леруа Мерлен», Askona);
• косметика и парфюмерия («Л’Этуаль», «Иль де Ботэ», Krasotka Pro);
• товары для детей («Детский мир», TOY, Mothercare);
• образование («Нетология», GeekBrains, SkillFactory);