[시큐어코딩 가이드] 종료되지 않는 반복문 또는 재귀 함수

 

 

 

■ 시간 및 상태

 

동시 또는 거의 동시 수행을 지원하는 병렬 시스템이나 하나 이상의 프로세스가 동작되는 환경에서 시간 및 상태를 부적절하게 관리하여 발생할 수 있는 보안약점이다.

 

종료되지 않는 반복문 또는 재귀 함수(시큐어코딩)

 

■ 개요

 

재귀의 순환 횟수를 제어하지 못하여 할당된 메모리나 프로그램 스택 등의 자원을 과다하게 사용하면 위험하다. 대부분의 경우, 귀납 조건(Base Case)이 없는 재귀 함수는 무한 루프에 빠져들게 되고 자원고갈을 유발함으로써 시스템의 정상적인 서비스를 제공할 수 없게 한다.


Python에서는 최대 재귀 깊이가 적용되어 있어 무한루프가 발생하지 않으나, setrecursionlimit()를 사용하여 임의로 최대 재귀 깊이를 변경하여 사용하는 경우 과도하게 많이 재귀 함수가 수행되지 않도록 주의하여야 한다.

 

 

■ 안전한 코딩 기법

 

모든 재귀 호출 시, 재귀 호출 횟수를 제한하거나, 초기 값을 설정(상수)하여 재귀 호출을 제한해야 한다. Python의recursionlimit 제한은 stack overflow를 막기 위한 방법이다. recursionlimit 값을 과도하게 큰 값으로 설정하지 않아야 한다.

 

 

코드예제

 

factorial 함수는 함수 내부에서 자신을 호출하는 함수로, 재귀문을 빠져 나오는 조건을 정의하고 있지 않아 시스템 장애를 유발할 수 있다.

 

안전하지 않은 코드의 예
def factorial(num):
# 재귀함수 탈출조건을 설정하지 않아 동작 중 에러 발생
return num * factorial(num – 1)

if __name__ == '__main__':
itr = 5
result = factorial(itr)
print(str(itr) + ' 팩토리얼 값은 : ' + str(result))

 

무한루프를 사용하지 않고 특정 조건 또는 횟수에 따라 동작한다.

 

안전한 코드의 예
def factorial(num):
# 재귀함수 사용 시에는 탈출 조건을 명시해야 한다.
if (num == 0):
return 1
else:
return num * factorial(num - 1)

if __name__ == '__main__':
itr = 5
result = factorial(itr)
print(str(itr) + ' 팩토리얼 값은 : ' + str(result))

 

Python의 재귀 반복 제한(Recursion Depth Limit)은 기본이 1000으로 설정되어 있다.


Anaconda의 경우는 기본 값이 2000이다. 이 값을 과도하게 변경하지 않아야 한다.

 

안전한 코드의 예
import sys

sys.setrecursionlimit(1000)

 

 

댓글

Designed by JB FACTORY