Skip to content

Commit dac804a

Browse files
committed
Fix makeslice panic in Dial #5
1 parent 79dc2ba commit dac804a

File tree

5 files changed

+92
-44
lines changed

5 files changed

+92
-44
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Set up Go 1.x
1919
uses: actions/setup-go@v2
2020
with:
21-
go-version: ^1.15
21+
go-version: ^1.16
2222

2323
- name: Check out code into the Go module directory
2424
uses: actions/checkout@v2
@@ -27,7 +27,7 @@ jobs:
2727
uses: golangci/golangci-lint-action@v2
2828
with:
2929
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
30-
version: v1.33
30+
version: v1.42.1
3131

3232
# Optional: working directory, useful for monorepos
3333
# working-directory: somedir

.golangci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ linters-settings:
4646
gocyclo:
4747
# minimal code complexity to report, 30 by default (but we recommend 10-20)
4848
min-complexity: 15
49+
cyclop:
50+
max-complexity: 15
4951
godox:
5052
keywords:
5153
- "BUG"
@@ -121,6 +123,7 @@ linters:
121123
enable-all: true
122124
disable:
123125
- gomnd
126+
- wrapcheck
124127

125128
issues:
126129
exclude:

CHANGELOG.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ All notable changes to this project will be documented in this file.
33

44
**ATTN**: This project uses [semantic versioning](http://semver.org/).
55

6-
## [Unreleased]
6+
## [Unreleased
7+
8+
## [v1.3.2] - 2022-05-16
9+
### Fixed
10+
- Fixed panic: runtime error: makeslice: len out of range in rcon.Dial #5
711

812
## [v1.3.1] - 2021-01-06
913
### Updated
@@ -74,7 +78,8 @@ changed.
7478
### Added
7579
- Initial implementation.
7680

77-
[Unreleased]: https://github.com/gorcon/rcon/compare/v1.3.1...HEAD
81+
[Unreleased]: https://github.com/gorcon/rcon/compare/v1.3.2...HEAD
82+
[v1.3.2]: https://github.com/gorcon/rcon/compare/v1.3.1...v1.3.2
7883
[v1.3.1]: https://github.com/gorcon/rcon/compare/v1.3.0...v1.3.1
7984
[v1.3.0]: https://github.com/gorcon/rcon/compare/v1.2.4...v1.3.0
8085
[v1.2.4]: https://github.com/gorcon/rcon/compare/v1.2.3...v1.2.4

rcon.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ func Dial(address string, password string, options ...Option) (*Conn, error) {
112112
if err := client.auth(password); err != nil {
113113
// Failed to auth conn with the server.
114114
if err2 := client.Close(); err2 != nil {
115-
//nolint:errorlint // TODO: Come up with the better wrapping
116115
return &client, fmt.Errorf("%w: %v. Previous error: %v", ErrMultiErrorOccurred, err2, err)
117116
}
118117

@@ -184,22 +183,27 @@ func (c *Conn) auth(password string) error {
184183
return err
185184
}
186185

186+
size := response.Size - PacketHeaderSize
187+
if size <= 0 {
188+
size = response.Size
189+
}
190+
187191
// When the server receives an auth request, it will respond with an empty
188192
// SERVERDATA_RESPONSE_VALUE, followed immediately by a SERVERDATA_AUTH_RESPONSE
189193
// indicating whether authentication succeeded or failed.
190194
// Some servers doesn't send an empty SERVERDATA_RESPONSE_VALUE packet, so we
191195
// do this case optional.
192196
if response.Type == SERVERDATA_RESPONSE_VALUE {
193197
// Discard empty SERVERDATA_RESPONSE_VALUE from authentication response.
194-
_, _ = c.conn.Read(make([]byte, response.Size-PacketHeaderSize))
198+
_, _ = c.conn.Read(make([]byte, size))
195199

196200
if response, err = c.readHeader(); err != nil {
197201
return err
198202
}
199203
}
200204

201205
// We must to read response body.
202-
buffer := make([]byte, response.Size-PacketHeaderSize)
206+
buffer := make([]byte, size)
203207
if _, err := c.conn.Read(buffer); err != nil {
204208
return fmt.Errorf("rcon: %w", err)
205209
}

rcon_test.go

Lines changed: 73 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,28 @@ import (
1717

1818
func authHandler(c *rcontest.Context) {
1919
switch c.Request().Body() {
20-
case c.Server().Settings.Password:
21-
rcon.NewPacket(rcon.SERVERDATA_RESPONSE_VALUE, c.Request().ID, "").WriteTo(c.Conn())
22-
rcon.NewPacket(rcon.SERVERDATA_AUTH_RESPONSE, c.Request().ID, "").WriteTo(c.Conn())
2320
case "invalid packet type":
2421
rcon.NewPacket(42, c.Request().ID, "").WriteTo(c.Conn())
2522
case "another":
2623
rcon.NewPacket(rcon.SERVERDATA_AUTH_RESPONSE, 42, "").WriteTo(c.Conn())
24+
case "makeslice":
25+
size := int32(len([]byte("")) + int(rcon.PacketPaddingSize)) // Some minecraft servers does not add header size
26+
27+
buffer := bytes.NewBuffer(make([]byte, 0, size+4))
28+
29+
_ = binary.Write(buffer, binary.LittleEndian, size)
30+
_ = binary.Write(buffer, binary.LittleEndian, c.Request().ID)
31+
_ = binary.Write(buffer, binary.LittleEndian, rcon.SERVERDATA_RESPONSE_VALUE)
32+
33+
// Write command body, null terminated ASCII string and an empty ASCIIZ string.
34+
buffer.Write(append([]byte(""), 0x00, 0x00))
35+
36+
buffer.WriteTo(c.Conn())
37+
38+
rcon.NewPacket(rcon.SERVERDATA_AUTH_RESPONSE, c.Request().ID, "").WriteTo(c.Conn())
39+
case c.Server().Settings.Password:
40+
rcon.NewPacket(rcon.SERVERDATA_RESPONSE_VALUE, c.Request().ID, "").WriteTo(c.Conn())
41+
rcon.NewPacket(rcon.SERVERDATA_AUTH_RESPONSE, c.Request().ID, "").WriteTo(c.Conn())
2742
default:
2843
rcon.NewPacket(rcon.SERVERDATA_AUTH_RESPONSE, -1, string([]byte{0x00})).WriteTo(c.Conn())
2944
}
@@ -129,6 +144,23 @@ func TestDial(t *testing.T) {
129144

130145
conn.Close()
131146
})
147+
148+
t.Run("makeslice", func(t *testing.T) {
149+
server := rcontest.NewServer(
150+
rcontest.SetSettings(rcontest.Settings{Password: "makeslice"}),
151+
rcontest.SetAuthHandler(authHandler),
152+
)
153+
154+
conn, err := rcon.Dial(server.Addr(), "makeslice")
155+
if err != nil {
156+
t.Errorf("got err %q, want %v", err, nil)
157+
server.Close()
158+
return
159+
}
160+
161+
conn.Close()
162+
server.Close()
163+
})
132164
}
133165

134166
func TestConn_Execute(t *testing.T) {
@@ -298,42 +330,46 @@ func TestConn_Execute(t *testing.T) {
298330
t.Run("pz server", func(t *testing.T) {
299331
needle := func() string {
300332
n := `List of server commands :
301-
* addalltowhitelist : Add all the current users connected with a password in the whitelist, so their account is protected.
302-
* additem : Add an item to a player, if no username is given the item will be added to you, count is optional, use /additem \"username\" \"module.item\" count, ex : /additem \"rj\" \"Base.Axe\" count
303-
* adduser : Use this command to add a new user in a whitelisted server, use : /adduser \"username\" \"pwd\"
304-
* addusertowhitelist : Add the user connected with a password in the whitelist, so his account is protected, use : /addusertowhitelist \"username\"
305-
* addvehicle : Spawn a new vehicle, use: /addvehicle \"script\" \"user or x,y,z\", ex /addvehicle \"Base.VanAmbulance\" \"rj\"
306-
* addxp : Add experience points to a player, use : /addxp \"playername\" perkname=xp, ex /addxp \"rj\" Woodwork=2
307-
* alarm : Sound a building alarm at the admin's position. Must be in a room.
308-
* banid : Ban a SteamID, use : /banid SteamID
309-
* banuser : Ban a user, add a -ip to also ban his ip, add a -r \"reason\" to specify a reason for the ban, use : /banuser \"username\" -ip -r \"reason\", ex /banuser \"rj\" -ip -r \"spawn kill\"
310-
* changeoption : Use this to change a server option, use : /changeoption optionName \"newValue\"
311-
* chopper : Start the choppers (do noise on a random player)
312-
* createhorde : Use this to spawn a horde near a player, use : /createhorde count \"username\", ex /createhorde 150 \"rj\", username is optional except from the server console.
313-
* godmod : Set a player invincible, if no username set it make you invincible, if no value it toggle it, use : /godmode \"username\" -value, ex /godmode \"rj\" -true (could be -false)
314-
* gunshot : Start a gunshot (do noise on a random player)
333+
* additem : Give an item to a player. If no username is given then you will receive the item yourself. Count is optional. Use: /additem "username" "module.item" count. Example: /additem "rj" Base.Axe 5
334+
* adduser : Use this command to add a new user to a whitelisted server. Use: /adduser "username" "password"
335+
* addvehicle : Spawn a vehicle. Use: /addvehicle "script" "user or x,y,z", ex /addvehicle "Base.VanAmbulance" "rj"
336+
* addxp : Give XP to a player. Use /addxp "playername" perkname=xp. Example /addxp "rj" Woodwork=2
337+
* alarm : Sound a building alarm at the Admin's position. (Must be in a room)
338+
* banid : Ban a SteamID. Use /banid SteamID
339+
* banuser : Ban a user. Add a -ip to also ban the IP. Add a -r "reason" to specify a reason for the ban. Use: /banuser "username" -ip -r "reason". For example: /banuser "rj" -ip -r "spawn kill"
340+
* changeoption : Change a server option. Use: /changeoption optionName "newValue"
341+
* chopper : Place a helicopter event on a random player
342+
* createhorde : Spawn a horde near a player. Use : /createhorde count "username". Example /createhorde 150 "rj" Username is optional except from the server console. With no username the horde will be created around you
343+
* createhorde2 : UI_ServerOptionDesc_CreateHorde2
344+
* godmod : Make a player invincible. If no username is set, then you will become invincible yourself. Use: /godmode "username" -value, ex /godmode "rj" -true (could be -false)
345+
* gunshot : Place a gunshot sound on a random player
315346
* help : Help
316-
* invisible : Set a player invisible zombie will ignore him, if no username set it make you invisible, if no value it toggle it, use : /invisible \"username\" -value, ex /invisible \"rj\" -true (could be -false)
317-
* kickuser : Kick a user, add a -r \"reason\" to specify a reason for the kick, use : /kickuser \"username\" -r \"reason\"
318-
* noclip : A player with noclip won't collide on anything, if no value it toggle it, use : /noclip \"username\" -value, ex /noclip \"rj\" -true (could be -false)
319-
* players : List the players connected
320-
* quit : Quit the server (but save it before)
321-
* releasesafehouse : Release a safehouse you are the owner of, use : /releasesafehouse
322-
* reloadlua : Reload a Lua script, use : /reloadlua \"filename\"
323-
* reloadoptions : Reload the options on the server (ServerOptions.ini) and send them to the clients
324-
* removeuserfromwhitelist : Remove the user from the whitelist, use: /removeuserfromwhitelist \"username\"
347+
* invisible : Make a player invisible to zombies. If no username is set then you will become invisible yourself. Use: /invisible "username" -value, ex /invisible "rj" -true (could be -false)
348+
* kick : Kick a user. Add a -r "reason" to specify a reason for the kick. Use: /kickuser "username" -r "reason"
349+
* lightning : Use /lightning "username", username is optional except from the server console
350+
* noclip : Makes a player pass through walls and structures. Toggles with no value. Use: /noclip "username" -value. Example /noclip "rj" -true (could be -false)
351+
* players : List all connected players
352+
* quit : Save and quit the server
353+
* releasesafehouse : Release a safehouse you own. Use /releasesafehouse
354+
* reloadlua : Reload a Lua script on the server. Use /reloadlua "filename"
355+
* reloadoptions : Reload server options (ServerOptions.ini) and send to clients
356+
* removeuserfromwhitelist : Remove a user from the whitelist. Use: /removeuserfromwhitelist "username"
357+
* removezombies : UI_ServerOptionDesc_RemoveZombies
358+
* replay : Record and play replay for moving player. Use /replay "playername" -record|-play|-stop filename. Example: /replay user1 -record stadion.bin
325359
* save : Save the current world
326-
* sendpulse : Toggle sending server performance info to this client, use : /sendpulse
327-
* servermsg : Use this to broadcast a message to all connected players, use : /servermsg my message !
328-
* setaccesslevel : Use it to set new access level to a player, acces level: admin, moderator, overseer, gm, observer. use : /setaccesslevel \"username\" \"accesslevel\", ex: /setaccesslevel \"rj\" \"moderator\"
329-
* showoptions : Show the list of current Server options with their values.
330-
* startrain : Start rain on the server
331-
* stoprain : Stop rain on the server
332-
* teleport : Teleport to a player, once teleported, wait 2 seconds to show map, use : /teleport \"playername\" or /teleport \"player1\" \"player2\", ex /teleport \"rj\" or /teleport \"rj\" \"toUser\"
333-
* teleportto : Teleport to coordinates, use: /teleportto x,y,z, ex /teleportto 100098,189980,0
334-
* unbanid : Unban a SteamID, use : /unbanid SteamID
335-
* unbanuser : Unban a player, use : /unbanuser \"username\"
336-
* voiceban : Block voice from user \"username\", use : /voiceban \"username\" -value, ex /voiceban \"rj\" -true (could be -false)`
360+
* servermsg : Broadcast a message to all connected players. Use: /servermsg "My Message"
361+
* setaccesslevel : Set access level of a player. Current levels: Admin, Moderator, Overseer, GM, Observer. Use /setaccesslevel "username" "accesslevel". Example /setaccesslevel "rj" "moderator"
362+
* showoptions : Show the list of current server options and values.
363+
* startrain : Starts raining on the server. Use /startrain "intensity", optional intensity is from 1 to 100
364+
* startstorm : Starts a storm on the server. Use /startstorm "duration", optional duration is in game hours
365+
* stoprain : Stop raining on the server
366+
* stopweather : Stop weather on the server
367+
* teleport : Teleport to a player. Once teleported, wait for the map to appear. Use /teleport "playername" or /teleport "player1" "player2". Example /teleport "rj" or /teleport "rj" "toUser"
368+
* teleportto : Teleport to coordinates. Use /teleportto x,y,z. Example /teleportto 10000,11000,0
369+
* thunder : Use /thunder "username", username is optional except from the server console
370+
* unbanid : Unban a SteamID. Use /unbanid SteamID
371+
* unbanuser : Unban a player. Use /unbanuser "username"
372+
* voiceban : Block voice from user "username". Use /voiceban "username" -value. Example /voiceban "rj" -true (could be -false)`
337373

338374
n = strings.Replace(n, "List of server commands :", "List of server commands : ", -1)
339375

0 commit comments

Comments
 (0)