정수 산술 결과의 잘못된 확장 또는 범위 초과 시프트

정수 산술 결과의 잘못된 확장 또는 범위 초과 시프트

설명

int 곱셈을 먼저 수행한 뒤 결과를 long으로 변환하면, 곱셈 단계에서 이미 오버플로우한 값이 그대로 확장됩니다. 또한 타입 폭 이상의 시프트는 언어의 시프트 거리 처리 규칙 때문에 개발자가 의도한 값과 다른 결과를 만들 수 있습니다. 이는 계산 정확성 문제이며, 보안 영향은 잘못된 결과가 크기 제한이나 접근 판단 등에 사용되는지에 따라 달라집니다.

잠재적 영향

  • 크기, 개수, 인덱스 계산 결과가 잘못될 수 있습니다.
  • 비트 마스크와 플래그가 의도와 다르게 계산될 수 있습니다.
  • 잘못된 중간 결과가 이후 로직에 전파되어 예측하기 어려운 동작을 만들 수 있습니다.

해결 방법

  1. 곱셈 전에 피연산자 중 하나를 long으로 변환합니다.
  2. 오버플로우를 오류로 처리해야 한다면 Math.multiplyExact를 사용합니다.
  3. 시프트 거리가 대상 타입의 비트 폭보다 작은지 확인합니다.
  4. 더 넓은 결과가 필요하다면 시프트 전에 값을 적절한 타입으로 변환합니다.

예시

곱셈 결과 확장

변경 전

java
public long calculateSize(int itemCount, int itemSize) {
    return (long) (itemCount * itemSize);
}

변경 후

java
public long calculateSize(int itemCount, int itemSize) {
    return (long) itemCount * itemSize;
}

설명:

  • 변경 전: 캐스팅 전에 int 곱셈이 수행되므로 중간 결과가 이미 오버플로우할 수 있습니다.
  • 변경 후: 피연산자를 먼저 long으로 변환하여 곱셈 전체를 long 범위에서 수행합니다.

시프트 연산

변경 전

java
public int buildMask(int flags) {
    return flags << 32;
}

변경 후

java
public long buildMask(int flags) {
    return ((long) flags) << 32;
}

설명:

  • 변경 전: Java의 int 시프트 거리는 하위 5비트만 사용하므로 32만큼의 시프트가 개발자의 기대와 다르게 처리됩니다.
  • 변경 후: 값을 long으로 먼저 변환하여 64비트 계산으로 수행합니다.

참조