Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[SnowOne 2024] Денис Фокин: В чём суть, или как понять твой код?

[SnowOne 2024] Денис Фокин: В чём суть, или как понять твой код?

Многие разработчики жалуются на чужой код: говорят, что он непонятный, плохой, требуют всё переписать. Опытные разработчики могут не узнавать даже собственный код. Что же говорить о машине — могут ли средства программного анализа вычленить суть кода?

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

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

jugnsk

May 01, 2024
Tweet

More Decks by jugnsk

Other Decks in Programming

Transcript

  1. В чём суть, или как понять твой код? Как абстрактная

    интерпретация помогает анализировать программы Денис Фокин, 2024 [email protected] https://t.me/levantarse 1
  2. Все средства хороши • операционная семантика (англ. Structural semantics). •

    денотационная семантика (denotational semantics). • аксиоматическая семантика. 13
  3. Операционная семантика: dead code public static void main(String[] args) {

    System.out.println("Children left the Gingerbread house."); for (int i = 1; i < 3; i++) { System.out.printf(“Another step number %d.%n", i--); } System.out.println("Children have arrived home."); } Children left the Gingerbread house. Another step number 1. Another step number 1. Another step number 1. … … Another step number 1. Another step number 1. Another step n > Build cancelled while executing task ':Main.main()' 1 2 3 4 1 3 2 4 16
  4. Операционная семантика: dead code public static void main(String[] args) {

    System.out.println("Children left the Gingerbread house."); for (int i = 1; i < 3; i++) { System.out.printf(«Another step number %d.%n", i--); } System.out.println("Children have arrived home."); } Children left the Gingerbread house. Another step number 1. Another step number 1. Another step number 1. … … Another step number 1. Another step number 1. Another step n > Build cancelled while executing task ':Main.main()' 1 2 3 4 1 3 2 4 код 17
  5. Хлебные крошки public static void main(String[] args) { System.out.println("Children left

    the Gingerbread house."); for (int i = 1; i < 3; i++) { System.out.printf("The counter is %d%n", i--); } System.out.println("Children have arrived home."); } Children left the Gingerbread house. Another step number 1. Another step number 1. Another step number 1. … … Another step number 1. Another step number 1. Another step number 1. Another step number 1. Another step n > Build cancelled while executing task ':Main.main()' 18
  6. Правила хлебных крошек • переходить от крошки к крошке •

    если не видишь крошек – ищи их в некоторой окрестности • и другие 19
  7. Операционная семантика • посетить инструкции программы • покрыть интересующее нас

    множество путей исполнения • вывести заключения о свойствах программы • из одной точки программы, можно достичь другой точки программы 21
  8. Ты мне веришь или нет? Аксиоматическая семантика позволяет вывести свойство

    достижимости • инструкции в программе • в зависимости от диапазона значений входных данных 23
  9. Solver в лесу Пряничный домик Дом Лодка у левого берега

    Нет волка Нет медведя в берлоге Мост цел (Мост цел ∧ ¬ Медведь ∧ Через мост ) ∨ (Лодка ∧ ¬ Волк) 26
  10. Памятник нерукотворный «в каждой естественной науке заключено столько истины, сколько

    в ней есть математики» Иммануил Кант Денотационная семантика – математическая модель программы 28
  11. Соответствие Галуа (D, ≥) (I, ≥) 1 1.1 1.2345 2

    2.00001 2.454 3 3.12 3.14 4 1 2 3 4 4.01 30
  12. Абстракция «абстракция сама по себе не является ошибкой, лишь бы

    только помнили, что то, от чего отвлекаются, все же существует» Лейбниц 33
  13. Вкратце Абстрактная интерпретация выражается, как наименьшая неподвижная точка системы уравнений,

    которые описывают интересующее нас свойство предмета анализа. Система уравнений решается итеративно, пока не достигается неподвижная точка. разберём далее… 34
  14. Наивный пример -1515*17 -?*? Abstract universe: {(+), (-), (±)} -(+)*(+)

    (-)*(+) (-) 37 (±) -1515*17 (+) (-) 1515*17 abstract concrete -2*2
  15. Наивный пример 2 -1515+17 -?+? Abstract universe: {(+), (-), (±)}

    -(+)+(+) (-)+(+) (±) 38 (±) -1515*17 (+) (-) 1515*17 abstract concrete -1515+17 -2*2
  16. Почему абстрактная интерпретация • Доказательство в сложных (компьютерных) системах слишком

    сложно для человека • Анализ и верификация поведения компьютерной системы неразрешим или приводит к комбинаторному взрыву в случае с машиной • Абстракция позволяет справиться со сложностью • Абстрактная интерпретация позволяет выполнять вычисления и доказательства на формализованных моделях объектов, систем, вычислений и их отношений 39
  17. Чем хороша абстрактная интерпретация? некоторые общие алгоритмы применимы к абстрактной

    интерпретации Например: A UNIFIED APPROACH TO GLOBAL PROGRAM OPTIMIZATION by Gary A. Kildall https://static.aminer.org/pdf/PDF/000/54 6/451/a_unified_approach_to_global_pro gram_optimization.pdf 40
  18. Гэри Килдалл (Gary A. Kildall) • “A unified approach to

    global program optimization” • https://static.aminer.org/pdf/PDF/000/546/451/a_unified_approach_to_global_program_optimization.pdf • Оптимизации применимы к абстрактной интерпретации 41 1 2 3 4 41
  19. public static void main(String[] args) { int a = 0;

    int b = 0; int c = 0; int d = 0; int e = 0; for (int i = 1; i < 10; i ++) { System.out.printf( "State %d: %d, %d, %d, %d, %d%n", i, a, b, c, d, e ); b = 2; d = a + b; e = b + c; c = 4; } } State 1: 0, 0, 0, 0, 0 State 2: 0, 2, 4, 2, 2 State 3: 0, 2, 4, 2, 6 State 4: 0, 2, 4, 2, 6 State 5: 0, 2, 4, 2, 6 State 6: 0, 2, 4, 2, 6 State 7: 0, 2, 4, 2, 6 State 8: 0, 2, 4, 2, 6 State 9: 0, 2, 4, 2, 6 Переменные перестают менять значение после этого шага. 42
  20. Термины {1,2,3} {1,2} {2,3} {1,3} 2 1 {} 3 47

    (L, ⊆) Максимальный элемент (Top) Минимальный элемент (Bottom) Элемент Точная верхняя граница (Join) Точная нижняя граница (Meet)
  21. Алгебра {1,2,3} {1,2} {2,3} {1,3} 2 1 {} 3 48

    T ⊥ b V(c) ^ (d) a a ^ b = c a v b = d a ^ c = c a ^ a = c (a v c) ^ b = (a ^ b) v (c ^ b) = d v c = c
  22. Решётки — инструмент для абстракции 50 [-2, 2] [-2, 1]

    [-1, 2] [-2, 0] [-1, 1] [0, 2] [-2, -1] [-1, 0] [0, 1] [1, 2] [-2, 2] [-1, 1] [0, 0] [1, 1] [2, 2] ⊥ ± + - ⊥ … … - 4 - 3 - 2 - 1 0 1 2 3 4 ⊥ ⊥
  23. Примеры алгебраических решёток 51 [-2, 2] [-2, 1] [-1, 2]

    [-2, 0] [-1, 1] [0, 2] [-2, -1] [-1, 0] [0, 1] [1, 2] [-2, 2] [-1, 1] [0, 0] [1, 1] [2, 2] ⊥ ± + - ⊥ … … -4 -3 -2 -1 0 1 2 3 4 ⊥ ⊥
  24. Примеры алгебраических решёток 52 ± + - ⊥ … …

    -4 -3 -2 -1 0 1 2 3 4 • Порядок (по возрастанию абстракции): • неинициализированное значение • конкретное целое числовое значение • абстрактное знаковое значение • абстрактное знаковое значение с неизвестным знаком
  25. Примеры алгебраических решёток 53 ± + - ⊥ … …

    -4 -3 -2 -1 0 1 2 3 4 При обработке состояний программы мы объединяем информацию из разных состояний о значении переменных. При объединении несравнимых элементов решётки или если одно из значений больше другого мы ищем подходящее значение в решётке.
  26. Примеры алгебраических решёток 54 Даже простейшая решётка из двух элементов

    полезна при анализе программ. Например, если необходимо найти использование неинициализированной переменной в коде. ⊥ ⊥
  27. Примеры алгебраических решёток 55 ⊥ ⊥ Integer integerObject = null;

    for (int i = 0; i < 2; i++) { if (i == 1) { integerObject = 42; } System.out.printf( "Integer object %d%n", integerObject ); }
  28. private static void someMethod(int arg) { int someVariable; someVariable =

    0; for (int i = 0; i < 3; i++) { switch (i) { case 1: someVariable = 42; break; case 2: someVariable += arg; break; } } } Примеры алгебраических решёток 56 ± + - ⊥ … … -4 -3 -2 -1 0 1 2 3 4 ± 0 ⊥ 42
  29. Функции и абстрактная интерпретация • наименьшее множество со свойством неподвижной

    точки функции или цикла • теорема Тарски • формулы для нахождения неподвижной точки Итерации до достижения неподвижной точки 57
  30. Абстрактная интерпретация: dead code public static void main(String[] args) {

    System.out.println("Children left the Gingerbread house."); for (int i = 1; i < 3; i++) { System.out.printf("The counter is %d%n", i--); } System.out.println("Children have arrived home."); } 1 2 3 4 1 3 2 4 код {i == 1} {i == 0} i < 3 i < 3 Итерация 1 Итерация 2 { i == 1} {i == 0} Неподвижная точка i < 3 { i == 1} 59
  31. Абстрактная интерпретация: constant propagation for (int i = 1; i

    < 10; i ++) { b = 2; d = a + b; e = b + c; c = 4; } if (e == 6) { System.out.println("Confidential data"); } 1 2 3 1. Первая итерация 2. Вторая итерация 3. Сравниваем результат 4. Абстракция не изменилась – неподвижная точка 5. Абстракция увеличилась – проверяем следующую итерацию 6. Если абстракция снова увеличилась -- применяем расширение (widening) 7. Пункт 4. 60
  32. Проблемы абстрактной интерпретации • бесконечные итерации в анализе • если

    ошибки • или бесконечные решётки • слишком долгие итерации • высота решётки 61
  33. Суть символьного исполнения x = ?, a = 0 x

    > 3 x>3, a=5 x<=3, a=0 int foo(int x) { int a = 0; if (x > 3) { a = 5; } return 10/a; } 2 64
  34. Суть символьного исполнения x = ?, a = 5 x

    > 3 x>3, a=6 x<=3, a=5 Позволяет: • Начать чинить. • Сообщить разработчику. • Написать тест и зафиксировать проблему. • Написать тест и зафиксировать корректное поведение. 2 65
  35. Проблемы символьного исполнения • внешние зависимости и бесконечные циклы и

    рекурсии • приводит к подмешиванию переоценки (overapproximation) • решатель (solver) может справиться не с любой задачей • огромное число путей исполнения даже в простых программах • экспоненциальный взрыв путей исполнения 67
  36. Вместе – лучше Абстрактная интерпретация • ложно положительные результаты •

    для логически необоснованных доменов • ложнонегативные результаты Символьное исполнение • постобработка с целью создания контрпримеров 69
  37. Текущие задачи: решётки Высота и структура решётки критичны для производительности

    и точности анализа. Чем ближе структура решётки к семантике объекта анализа, тем точнее анализ. Но точность приводит к снижению производительности. 70 [-2, 2] [-2, 1] [-1, 2] [-2, 0] [-1, 1] [0, 2] [-2, -1] [-1, 0] [0, 1] [1, 2] [-2, 2] [-1, 1] [0, 0] [1, 1] [2, 2] ⊥ ± + - ⊥ … … -4 -3 -2 -1 0 1 2 3 4 ⊥ ⊥
  38. Текущие задачи: неподвижные точки Предсказание неподвижных точек в ряде числовых

    доменов демонстрирует хорошие результаты. Точное предсказание неподвижных точек, например, в строковых абстрактных доменах может значительно увеличить точность анализа. 71 let a, b, c, d, e a = 1 c = 0 for (let z = 0; z < 1000; z++ ) { b = 2 d = a + b e = b + c c = 4 } Kildall. G. A., A unified approach to global program optimization. Conference Record of the First ACM Symposium on Principles of Programming Languages, October 1973, page 194-206.
  39. Текущие задачи: новые числовые домены 72 1. Gagandeep Singh, Markus

    Püschel, and Martin Vechev. 2017. Fast polyhedra abstract domain. In Proceedings of the 44th ACM SIGPLAN Symposium on Principles of Programming Languages. 2. Miné A.. 2001. The octagon abstract domain. In Proceedings of the 8th Working Conference on Reverse Engineering. Существует более 1 решения даже для числового домена. Например, абстрактный домен Polyhedra1, абстрактный домен Octagon2. Новая реализация числового домена может улучшить производительность и точность анализа.