Old School Ops

RF455-049 RF 4.55: the client crashes on every login while the character has an item on the auction house (1E/19 names an item that isn't in the bag)

Game server RF Online: Dragonborn v0.2.0 high · filed by cybercyber
New

Game: RF 4.55 (Dragonborn), server v0.2.0, Windows build (stock gameserver.exe, SHA-256 96452fbd…).

Client: the supported Taiwan build, RF_Online.bin SHA-256 46528aac…2bbc558 (2025-07-16), Language=Taiwan.

Summary

  • After a character registers an item on the auction house, the client closes itself on every world entry with that character. It closes right as the world finishes loading, with no message.
  • The character can't play until the listing sells or expires. It can't cancel the listing, because it never gets into the world. Other characters on the account are fine.
  • Cause: at world entry the server sends 1E/19 unmannedtrader_Regist_item_inform_zocl. The client looks up each entry's item in the bag and uses the result without checking it.
    • The server has already taken the item out of the bag, and names it with a fresh serial.
    • Its entries are 18 bytes, and the client reads 23, so even the serial the client reads isn't the one sent.
    • The lookup returns nothing, and the client reads through a null pointer.

Steps to reproduce

  1. Enter the world with any character, open the auction house at an NPC store, and register an item. For example, register a stack of 99 potions.
  2. The server logs atrade register {"listing": 1, ...}, and the item leaves the bag. The DB has the listing in atrade_listings and no row for the item in character_items.
  3. Go back to character select, or log out, and enter the world with the same character.
  4. The client closes as the world loads. The server logs only the dropped connection:
client entered world {"session": 1, "name": "Helios", ...}
tcpnet: session 1 read error: ... wsarecv: An existing connection was forcibly closed by the remote host.
client disconnected {"session": 1, ...}
  1. Every later attempt does the same (seen at 20:50:13 and 20:51:05).

What the server sends

(*Server).sendATradeWorldEntry (0x140760f40) builds one entry per open listing:

  • 0x140761bc0: (*client).allocItemSerial hands out a new serial for the listed item;
  • 0x140761be6: (*Server).rememberATradeSerial records it. It's never added to the bag.
  • 0x140761405: protocol.ATradeRegistItemInform (0x14063cc60) packs it.
u8 count, then count × { u16 serial, u32, u32, u32, u32 }       (18-byte entries)

0x14063cd74 stores the word at body+1+18·i, then dwords at +3, +7, +0xB and +0xF.

What the client reads

The 1E/19 handler is at 0x59c250 in RF_Online.bin. It reads 23-byte entries (stride 0x17):

u8 count, then count × { u8 (+0), u16 item serial (+1), u32 (+3), u32 (+7), u32 (+0xB), ..., u16 (+0x13) }

For each entry:

  1. 0x59c2c8: 0x4fae40 looks the serial up in the bag (board 0).
  2. The result goes unchecked to the registered-items board's add, 0x4bf0a0 (board 0x1B).
  3. 0x4bf0d8: that calls 0x412000, which reads [item + 0x248]. A null item crashes there: an access violation at 0x41200f, reading 0x248.

The client expects a registered item to still be in the bag, under the serial 1E/19 names.

Suggested fix

Keep a registered item in the bag, locked, under the serial that 1E/19 sends. Remove it when it sells; unlock it or return it when the listing is cancelled or expires. character_items.item_locked already exists.

If the item can't stay in the bag, leave such listings out of 1E/19. The listing still sells and expires; the client's auction window just won't show it as registered.

Workaround

A local client patch (atrade-missing-item, 2 sites) skips an entry whose bag lookup finds nothing. It does that with a test/je stub in the int3 padding after the handler. With it, login works and the listing still sells or expires, but a stock client still crashes, so the fix belongs on the server.

Reported on version 0.2.0

History

  • cybercyber filed it ·

Replies

Nobody has replied yet.

Sign in to comment.

Where the xp came from

Last 30 days

Loading…

Open the full search page