원문 캡처 · tenderlovemaking.com
원문 캡처 · tenderlovemaking.com

초기화되지 않은 변수를 위한 정적 분석

초기화되지 않았을 가능성이 있는 변수를 찾는 정적 분석 기법을 설명하고, 이를 Ruby 코드에 적용하는 과정을 소개한다. 이 기법은 TIP이라는 간단한 언어의 예제로 시작해 이분 그래프와 제어 흐름 그래프를 활용한 분석기를 구현한 뒤, Prism으로 Ruby 코드를 파싱해 같은 분석 틀에 연결한다.

분석 대상은 변수가 초기화됐는지, 초기화되지 않았을 가능성이 있는지다. 조건문처럼 실행 경로를 미리 알 수 없는 경우에는 각 경로의 상태를 합쳐 보수적으로 판단한다. 예를 들어 한 경로에서 c에 값을 대입하고 다른 경로에서는 대입하지 않으면, 조건문 뒤의 c는 초기화되지 않았을 가능성이 있다고 본다.

각 코드 줄의 데이터 흐름 규칙은 이분 그래프로 나타낸다. 글에서는 변수와 ‘초기화되지 않음’을 노드로 두고, 상태가 다음 줄로 어떻게 전달되는지 간선으로 표현한다. 이 그래프들을 제어 흐름 그래프와 함께 순회하면 각 지점에서 초기화되지 않았을 가능성이 있는 변수를 계산할 수 있다.

Ruby 예제에서는 Prism으로 구문 트리를 읽고, 변수 대입과 참조에 따라 TIP에서 수작업으로 정의한 것과 같은 데이터 흐름 규칙을 기록한다. 예제의 b = a + c는 c가 아직 대입되지 않은 상태이므로 실제 Ruby에서 실행하면 NameError가 발생한다. 분석기는 이처럼 대입 전 변수 참조를 찾는 데 쓰인다.

전체 프로그램 코드는 GitHub Gist에서 볼 수 있다. 글은 추적하는 사실의 집합이 유한하고 전달 함수가 분배적이면 같은 틀을 다른 분석에도 활용할 수 있다고 설명한다. 예로 신뢰할 수 없는 데이터가 변수에 들어 있는지 확인하는 오염 분석과, 어느 실행 경로에서도 변수 값이 바뀌기 전에 반드시 계산되는 ‘매우 바쁜 표현식’ 분석을 든다. 글에서 소개한 구현은 IFDS 프레임워크의 일부를 생략했다.