Skip to content

[FB-235] Lua 런타임·builtin 잔여 결함 모음(수명·형 변환·스택) #656

Closed as not planned

Description

@boyism80
  • 심각도: low
  • 근거 강도: 항목별 보통~약함 (대부분 호출처 0이거나 µs 창, 잠재 UAF 포함)
  • 대상 커밋: 8576836 (대표 항목은 이 HEAD에서 코드로 다시 확인, 나머지는 기록 당시 판단 기준이라 수정 확인 때 항목별로 다시 봐요)
  • 출처: P03·P09·P22 회차(102·134·141·157·171·179·187·199·211회차 등)

이 이슈는 '기준 미달 후보도 모두 이슈로 등록'(2026-10-16 사용자 지시)에 따라, 과거 정기 검수·push 리뷰에서 기록만 하던 후보를 영역별로 모은 것이에요. 항목마다 데이터 복제·크래시·로그인 불가가 아니어서 이전 기준에는 못 미쳤어요. 이미 고쳐진 것, 기존 이슈와 겹치는 것, 예외 목록·사용자 확인 의도, 크래시 전제 시나리오는 뺐어요. 항목별로 따로 처리하기 원하시면 나눌게요.

항목

  1. reload_scripts: 다운로드 rename이 파일별이라 중간 실패 시 디스크 부분 교체, root별 dump 중간 실패 시 스레드마다 다른 스크립트 판, 실패 dump의 빈 bytecode 캐시가 invalidate 전까지 남음 — context_pool/download_scripts
  2. abort↔finish_resume의 _running 비원자 갱신(µs 경합) — server/fb/src/lua.cpp
  3. tonumber/lua_tointeger 실수→정수 static_cast UB·절단(FB-133 계열 잔여)
  4. take_dialog 뒤 switching 예외 시 Lua 슬롯 미반납(종료 중), context 풀 상한 1000 × 대화 대기 시 풀 고갈 가능
  5. group/clan 콜백형 비동기 lua_call 경로(호출처 0)
  6. builtin spawn_mob 위치 테이블 + 인자 3개면 x,y 미초기화(호출처 0)
  7. builtin_menu 루프에서 rawgeti pop 누락(선택지 수가 작아 스택 여유 안)
  8. builtin_item 행 루프가 테이블에 없는 이름이면 continue로 값 pop을 건너뛰어 lua_next 오류·행 밀림(마켓 '알 수 없는 아이템' 표시)
  9. quest builtin이 raw quest 포인터를 스레드 hop 너머로 캡처, push_achievement/erase_achievement 뒤 Lua에 넘긴 업적 userdata 댕글링, clan:members()가 멤버 원시 포인터를 Lua에 넘김(잠재 UAF, 현재 스크립트 사용 없음)
  10. door builtin이 문 raw 포인터와 throw하는 maps[id]를 사용(인스턴스 파괴 뒤 재호출 시 예외·UAF 여지)
  11. clan builtin id/name/members/title/allied/is_* 읽기가 가드 없이 lazy_container 상태 접근
  12. dialog/list appearance를 yield 전 Lua 스레드에서 create+.release() → builder 실패 시 누수
  13. item_by_uid가 co_builder 없이 다른 스레드 캐릭터 인벤토리 조회(호출처 없음)
  14. exchange money·count가 비정수 float면 lua_tointeger 0 → 비용 없이 보상(현재 스크립트는 정수만 넘김)
  15. stored_item(index)·items::retrieve(index)가 빈 창고에서 size()-1 wrap으로 범위 검사를 통과해 vector::at 예외
  16. normal_attack_damage가 스레드 hop 전에 assert_thread(DEBUG 전용)
  17. id2ch가 nil push 후 0 반환(반환값 개수 불일치, 표면)

수정 방향

  • reload는 새 판을 임시 위치에 모두 받은 뒤 원자 교체하고, root 전체 dump가 성공해야 게시해요.
  • Lua로 넘기는 객체는 weak 기반 userdata로 통일하고, raw 포인터 반환 builtin을 정리해요.
  • 수 변환은 lua_tointegerx로 정수 여부를 검사하고 실패를 오류로 돌려요. 스택 pop 누락은 lua_gettop 균형 검사로 고쳐요.
  • 빈 컨테이너 index 가드는 index >= size() 형태로 바꿔요.

Activity

  1. boyism80 commented on Oct 16, 2026

    @boyism80
    OwnerAuthor

    실제로 고친 것은 8번 ch:item 대화입니다. 아이템 이름을 찾지 못해 행을 넘길 때 lua_next가 올려 둔 값을 pop하지 않아 다음 행이 밀리던 것을, 행을 목록에 넣지 않는 경우에도 값을 항상 빼도록 고쳤습니다.

    나머지는 무시합니다.

    • 스크립트 reload의 dump·파일별 교체는 실패 가능성이 거의 없고, 다운로드는 전부 받은 뒤에만 디스크에 씁니다.
    • abort는 _running을 건드리지 않습니다. 증감은 그 Lua 스레드의 resume 안에만 있습니다.
    • lua_tointeger는 정수가 아니면 0을 반환합니다. exchange에 소수가 들어가면 비용이 0이 되지만 스크립트는 정수만 넘깁니다.
    • 대화 슬롯은 파이프라인 실패 시 reject되고 컨텍스트 가드가 풀에 돌려줍니다. take_dialog는 없습니다.
    • ch:group(function), ch:clan(function), item_by_uid, 위치 테이블 spawn_mob은 스크립트 호출이 없습니다.
    • menu 선택지 스택은 함수가 끝나면 Lua가 맞춥니다.
    • 퀘스트·업적·문 포인터와 clan:members()는 스크립트가 값을 양보 너머로 들고 있지 않습니다.
    • 빈 창고의 size() - 1 언더플로는 숫자 인덱스 호출이 없습니다.
    • normal_attack_damage의 assert_thread는 DEBUG 전용이고 실제 호출은 자기 캐릭터입니다. id2ch가 0을 반환해도 Lua에서는 nil과 같습니다.
    • appearance 누수는 스레드 전환 실패 시 객체 하나입니다.
  2. boyism80 commented on Oct 16, 2026

    @boyism80
    OwnerAuthor

    [FB 리뷰어] 피드백 반영했습니다.

    • 항목 8 (ch:item / builtin_item 대화): 수정 보고 접수. develop HEAD 1a672d602의 server/game/src/builtin/character.cpp builtin_item 루프는 아직 이름을 못 찾아 item == nullptr일 때 continue로 lua_next value pop을 건너뜁니다. push 오면 코드로 재확인한 뒤 이슈를 닫겠습니다.
    • 항목 1–7·9–17: 무시·예외 등록. 같은 패턴은 다시 지적하지 않습니다.
      • reload dump·파일별 교체 실패 가능성·다운로드 전부 수신 후 기록
      • abort가 _running을 건드리지 않음(증감은 해당 Lua 스레드 resume만)
      • lua_tointeger 비정수→0·exchange는 스크립트가 정수만 넘김
      • 대화 슬롯은 파이프라인 실패 시 reject·컨텍스트 가드 반납(take_dialog 없음)
      • ch:group(function)/ch:clan(function)/item_by_uid/위치 테이블 spawn_mob 스크립트 호출 없음
      • menu 선택지 스택은 함수 종료 시 Lua가 맞춤
      • 퀘스트·업적·문 포인터·clan:members()는 스크립트가 yield 너머로 값을 들고 있지 않음
      • 빈 창고 size()-1 언더플로는 숫자 인덱스 호출 없음
      • normal_attack_damage의 assert_thread는 DEBUG 전용·실제 호출은 자기 캐릭터
      • id2ch 0 반환은 Lua에서 nil과 동일
      • appearance 누수는 스레드 전환 실패 시 객체 하나

    이슈는 항목 8 검증용으로 open 유지합니다.

  3. boyism80 commented on Oct 16, 2026

    @boyism80
    OwnerAuthor

    [FB 리뷰어] 사용자 지시(2026-10-17 00:10 KST)에 따라 기준 미달 항목은 이슈 대상에서 제외해 not planned로 닫아요. 내용은 audit 문서에 남겨 두고, 앞으로 기준 미달 항목은 묶음 브리핑에 한 줄로만 알려요.

  4. boyism80 commented on Oct 16, 2026

    @boyism80
    OwnerAuthor

    [FB 리뷰어] db0feb076에서 8번(ch:item lua_next pop) 수정을 확인했어요. item이 없을 때도 continue 없이 마지막 lua->pop(1)까지 가서 스택이 맞아요. 이슈는 닫힌 상태로 둘게요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions