46. 널 종료 문자열 필드 파싱의 프레임 경계 미준수 (오배열·프레임 오염, C#)

난이도 중 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// 시나리오: 로그인 패킷의 페이로드 파싱 (C# 게임서버)
// - 상위 수신 루프가 길이 프리픽스로 "이 논리 메시지"의 바이트 범위
//   [offset, offset+frameLen) 를 이미 잘라서 넘겨준다.
// - 페이로드 레이아웃: [널 종료 문자열: 계정명]['\0']['uint16 클라이언트 버전']
//   즉 계정명은 C 스타일 널 종료 문자열이고, 그 뒤에 2바이트 버전이 온다.
// - 계정명은 신뢰할 수 없는 클라이언트 입력이며, 악성/손상 패킷은 널 종료
//   바이트를 생략하거나 프레임 경계까지 채워 보낼 수 있다.
//
// 과제: 아래 파서는 정상 패킷은 잘 처리하지만, 특정 입력에서 프레임 밖의
//       바이트를 읽거나 다음 필드를 계정명으로 오인해 파싱이 어긋난다.
//       (A),(B) 를 근거로 문제와 수정안을 설명하라.

using System;
using System.Text;

public static class LoginParser
{
    // buffer: 세션 수신 링버퍼(여러 프레임이 연속으로 쌓여 있음)
    // offset..offset+frameLen: 이번 메시지의 범위
    public static (string account, ushort version) Parse(byte[] buffer, int offset, int frameLen)
    {
        int nul = Array.IndexOf(buffer, (byte)0, offset);   // (A)
        int nameLen = nul - offset;

        string account = Encoding.UTF8.GetString(buffer, offset, nameLen);

        int p = nul + 1;
        ushort version = (ushort)(buffer[p] | (buffer[p + 1] << 8)); // (B)
        return (account, version);
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.