Subject: [bug#33347] [PATCH 4/4] gnu: teeworlds: Update to 0.7.0 [fixes CVE-2018-18541].

From: Alex Vong <[email-masked]>
Date: Thu, 15 Nov 2018 05:14:50 +0800

Leo Famulari <[email-masked]> writes:

> On Wed, Nov 14, 2018 at 09:36:25PM +0800, Alex Vong wrote:
>> Well, I though we have a policy to remove bundle dependencies in order
>> to avoid building the same library many times. Do we make exceptions for
>> shared libraries w/o a build system? (an exception I can think of is
>> gnulib)
>
> In general, yes, our policy is to unbundle things when practical.
>
> But there are some commonly used software implementations of basic
> functions (like base64, sha1 (most hash functions actually), et cetera)
> that are specifically designed to be copied and pasted into the
> application that will be using them.
>
> You can usually tell this is the case because the thing will not have
> any build system at all, like you suggest. Also because you find the
> same copy-pasted code in almost every program you look at, like with
> base64 and the hash functions.
>
>> Besides, the FIXME comment seems to suggest future readers to help
>> remove the bundled pnglite. Debian also removes the bundled pnglite in
>> teeworlds[0].
>
> Well, at a certain point it becomes a matter of taste, and the choice
> should be made by the person doing the work — you! Either way is fine
> for Guix :) The important thing is to get this Teeworlds fix pushed
> without too much delay.

Yes, we should get it fix fast :) I decide not to unbundle md5 because I
actually need to use a hack to make teeworlds build with libmd. But I
still have pnglite unbundle because it looks standalone enough for me
and no hacks are required to unbundle. Here are the new patches:

From 5e7cb656306622e88352332c6ed9668d8afc60c4 Mon Sep 17 00:00:00 2001
From: Alex Vong <[email-masked]>
Date: Mon, 12 Nov 2018 01:55:05 +0800
Subject: [PATCH 1/4] gnu: Add pnglite.

* gnu/packages/image.scm (pnglite): New variable.
---
 gnu/packages/image.scm | 56 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/gnu/packages/image.scm b/gnu/packages/image.scm
index 9bf9bd7e5..6c025e02f 100644
--- a/gnu/packages/image.scm
+++ b/gnu/packages/image.scm
@@ -21,6 +21,7 @@
 ;;; Copyright © 2018 Pierre Neidhardt <[email-masked]>
 ;;; Copyright © 2018 Marius Bakke <[email-masked]>
 ;;; Copyright © 2018 Pierre-Antoine Rouby <[email-masked]>
+;;; Copyright © 2018 Alex Vong <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -253,6 +254,61 @@ files.  It can compress them as much as 40% losslessly.")
   ;; This package used to be wrongfully name "pngcrunch".
   (deprecated-package "pngcrunch" pngcrush))
 
+(define-public pnglite
+  (let ((commit "11695c56f7d7db806920bd9229b69f230e6ffb38")
+        (revision "1"))
+    (package
+      (name "pnglite")
+      ;; The project was moved from sourceforge to github.
+      ;; The latest version in sourceforge was 0.1.17:
+      ;; https://sourceforge.net/projects/pnglite/files/pnglite/
+      ;; No releases are made in github.
+      (version (git-version "0.1.17" revision commit))
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                      (url "https://github.com/dankar/pnglite")
+                      (commit commit)))
+                (sha256
+                 (base32
+                  "1lmmkdxby5b8z9kx3zrpgpk33njpcf2xx8z9bgqag855sjsqbbby"))
+                (file-name (git-file-name name version))))
+      (build-system gnu-build-system)
+      (arguments
+       `(#:tests? #f ; no tests
+         #:phases
+         (modify-phases %standard-phases
+           (delete 'configure)
+           (replace 'build
+             (lambda _
+               ;; common build flags for building shared libraries
+               (let ((cflags '("-O2" "-g" "-fPIC"))
+                     (ldflags '("-shared")))
+                 (apply invoke
+                        `("gcc"
+                          "-o" "libpnglite.so"
+                          ,@cflags
+                          ,@ldflags
+                          "pnglite.c"))
+                 #t)))
+           (replace 'install
+             (lambda* (#:key outputs #:allow-other-keys)
+               (let* ((out (assoc-ref outputs "out"))
+                      (lib (string-append out "/lib/"))
+                      (include (string-append out "/include/"))
+                      (doc (string-append out "/share/doc/"
+                                          ,name "-" ,version "/")))
+                 (install-file "libpnglite.so" lib)
+                 (install-file "pnglite.h" include)
+                 (install-file "README.md" doc)
+                 #t))))))
+      (inputs `(("zlib" ,zlib)))
+      (home-page "https://github.com/dankar/pnglite")
+      (synopsis "Pretty small png library")
+      (description "A pretty small png library.
+Currently all documentation resides in @file{pnglite.h}.")
+      (license license:zlib))))
+
 (define-public libjpeg
   (package
    (name "libjpeg")
-- 
2.19.1

From e786c6e470a6930af9107e9722bea95a03c5d1c9 Mon Sep 17 00:00:00 2001
From: Alex Vong <[email-masked]>
Date: Mon, 12 Nov 2018 02:23:27 +0800
Subject: [PATCH 2/4] gnu: Add json-parser.

* gnu/packages/web.scm (json-parser): New variable.
---
 gnu/packages/web.scm | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/gnu/packages/web.scm b/gnu/packages/web.scm
index 03deab422..cde3d00c1 100644
--- a/gnu/packages/web.scm
+++ b/gnu/packages/web.scm
@@ -28,6 +28,7 @@
 ;;; Copyright © 2018 Pierre-Antoine Rouby <[email-masked]>
 ;;; Copyright © 2018 Gábor Boskovits <[email-masked]>
 ;;; Copyright © 2018 Mădălin Ionel Patrașcu <[email-masked]>
+;;; Copyright © 2018 Alex Vong <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -582,6 +583,37 @@ It aims to conform to RFC 7159.")
                    (("-Werror") ""))
                  #t))))))
 
+(define-public json-parser
+  (package
+    (name "json-parser")
+    (version "1.1.0")
+    (source (origin
+              ;; do not use auto-generated tarballs
+              (method git-fetch)
+              (uri (git-reference
+                    (url "https://github.com/udp/json-parser.git")
+                    (commit (string-append "v" version))))
+              (file-name (git-file-name name version))
+              (sha256
+               (base32
+                "1ls7z4fx0sq633s5bc0j1gh36sv087gmrgr7rza22wjq2d4606yf"))))
+    ;; FIXME: we should build the python bindings in a separate package
+    (build-system gnu-build-system)
+    ;; the tests are written for the python bindings which are not built here
+    (arguments '(#:tests? #f))
+    (home-page "https://github.com/udp/json-parser")
+    (synopsis "JSON parser written in ANSI C")
+    (description "This package provides a very low footprint JSON parser
+written in portable ANSI C.
+
+@itemize
+@item BSD licensed with no dependencies (i.e. just drop the C file into your
+project)
+@item Never recurses or allocates more memory than it needs
+@item Very simple API with operator sugar for C++
+@end itemize")
+    (license l:bsd-2)))
+
 (define-public qjson
   (package
     (name "qjson")
-- 
2.19.1

From b1cdc9568f8d82ed7096328d0b3845fc32b4efe8 Mon Sep 17 00:00:00 2001
From: Alex Vong <[email-masked]>
Date: Thu, 8 Nov 2018 10:53:43 +0800
Subject: [PATCH 3/4] gnu: bam: Update to 0.5.1.

* gnu/packages/build-tools.scm (bam): Update to 0.5.1.
[source]: Switch to git-fetch.
[arguments]: Use newly provided Makefile.
[inputs]: Add lua.
---
 gnu/packages/build-tools.scm | 37 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/gnu/packages/build-tools.scm b/gnu/packages/build-tools.scm
index 42de56f8c..a52ee480a 100644
--- a/gnu/packages/build-tools.scm
+++ b/gnu/packages/build-tools.scm
@@ -5,6 +5,7 @@
 ;;; Copyright © 2018 Fis Trivial <[email-masked]>
 ;;; Copyright © 2018 Tomáš Čech <[email-masked]>
 ;;; Copyright © 2018 Marius Bakke <[email-masked]>
+;;; Copyright © 2018 Alex Vong <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -30,6 +31,7 @@
   #:use-module (guix build-system cmake)
   #:use-module (gnu packages)
   #:use-module (gnu packages compression)
+  #:use-module (gnu packages lua)
   #:use-module (gnu packages python)
   #:use-module (gnu packages python-crypto)
   #:use-module (gnu packages python-web)
@@ -40,33 +42,30 @@
 (define-public bam
   (package
     (name "bam")
-    (version "0.4.0")
+    (version "0.5.1")
     (source (origin
-              (method url-fetch)
-              (uri (string-append "http://github.com/downloads/matricks/"
-                                  "bam/bam-" version ".tar.bz2"))
+              ;; do not use auto-generated tarballs
+              (method git-fetch)
+              (uri (git-reference
+                    (url "https://github.com/matricks/bam.git")
+                    (commit (string-append "v" version))))
+              (file-name (git-file-name name version))
               (sha256
                (base32
-                "0z90wvyd4nfl7mybdrv9dsd4caaikc6fxw801b72gqi1m9q0c0sn"))))
+                "13br735ig7lygvzyfd15fc2rdygrqm503j6xj5xkrl1r7w2wipq6"))))
     (build-system gnu-build-system)
     (arguments
-     `(#:phases
+     `(#:make-flags `("CC=gcc"
+                      ,(string-append "INSTALL_PREFIX="
+                                      (assoc-ref %outputs "out")))
+       #:test-target "test"
+       #:phases
        (modify-phases %standard-phases
-         (delete 'configure)
-         (replace 'build
-           (lambda _
-             (zero? (system* "bash" "make_unix.sh"))))
-         (replace 'check
-           (lambda _
-             (zero? (system* "python" "scripts/test.py"))))
-         (replace 'install
-           (lambda* (#:key outputs #:allow-other-keys)
-             (let ((bin (string-append (assoc-ref outputs "out") "/bin")))
-               (mkdir-p bin)
-               (install-file "bam" bin)
-               #t))))))
+         (delete 'configure))))
     (native-inputs
      `(("python" ,python-2)))
+    (inputs
+     `(("lua" ,lua)))
     (home-page "https://matricks.github.io/bam/")
     (synopsis "Fast and flexible build system")
     (description "Bam is a fast and flexible build system.  Bam uses Lua to
-- 
2.19.1

From 3aa13808d20fcf2eea585c85b96e8f6b1f5fe292 Mon Sep 17 00:00:00 2001
From: Alex Vong <[email-masked]>
Date: Mon, 12 Nov 2018 02:42:25 +0800
Subject: [PATCH 4/4] gnu: teeworlds: Update to 0.7.0 [fixes CVE-2018-18541].

* gnu/packages/games.scm (teeworlds): Update to 0.7.0.
[source]: Switch to git-fetch. Remove all bundled libraries except md5.
[arguments]: Adjust accordingly.
[inputs]: Use sdl2 instead of sdl and python-wrapper instead of python-2.
Add json-parser and pnglite.
* gnu/packages/patches/teeworlds-use-latest-wavpack.patch: Update it.
---
 gnu/packages/games.scm                        | 116 ++++++++++++------
 .../teeworlds-use-latest-wavpack.patch        |  72 ++++++++---
 2 files changed, 136 insertions(+), 52 deletions(-)

diff --git a/gnu/packages/games.scm b/gnu/packages/games.scm
index 3679aa09c..a1a571c51 100644
--- a/gnu/packages/games.scm
+++ b/gnu/packages/games.scm
@@ -35,6 +35,7 @@
 ;;; Copyright © 2018 Tim Gesthuizen <[email-masked]>
 ;;; Copyright © 2018 Madalin Ionel-Patrascu <[email-masked]>
 ;;; Copyright © 2018 Benjamin Slade <[email-masked]>
+;;; Copyright © 2018 Alex Vong <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -4139,31 +4140,54 @@ small robot living in the nano world, repair its maker.")
 (define-public teeworlds
   (package
     (name "teeworlds")
-    (version "0.6.4")
+    (version "0.7.0")
     (source (origin
-              (method url-fetch)
-              (uri (string-append "https://github.com/teeworlds/teeworlds/"
-                                  "archive/" version "-release.tar.gz"))
-              (file-name (string-append name "-" version ".tar.gz"))
+              ;; do not use auto-generated tarballs
+              (method git-fetch)
+              (uri (git-reference
+                    (url "https://github.com/teeworlds/teeworlds.git")
+                    (commit version)))
+              (file-name (git-file-name name version))
               (sha256
                (base32
-                "1mqhp6xjl75l49050cid36wxyjn1qr0vjx1c709dfg1lkvmgs6l3"))
-              (modules '((guix build utils)))
-              (snippet
-               '(begin
-                  (for-each delete-file-recursively
-                            '("src/engine/external/wavpack/"
-                              "src/engine/external/zlib/"))
+                "0jigg2yikihbivzs7hpljr0mghx1l9v4f1cdr8fbmqv2wb51ah8q"))
+              (modules '((guix build utils)
+                         (ice-9 ftw)
+                         (ice-9 regex)
+                         (srfi srfi-1)
+                         (srfi srfi-26)))
+              (snippet ; remove bundled libraries except md5
+               '(let ((base-dir "src/engine/external/"))
+                  (for-each (compose (cut delete-file-recursively <>)
+                                     (cut string-append base-dir <>))
+                            (remove (cut string-match "(^.)|(^md5$)" <>)
+                                    (scandir base-dir)))
                   #t))
               (patches
                (search-patches "teeworlds-use-latest-wavpack.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:tests? #f ; no tests included
+       #:modules ((guix build gnu-build-system)
+                  (guix build utils)
+                  (srfi srfi-26))
        #:phases
        (modify-phases %standard-phases
          (replace 'configure
            (lambda* (#:key outputs #:allow-other-keys)
+             ;; The bundled json-parser uses an old API.
+             ;; To use the latest non-bundled version, we need to pass the
+             ;; length of the data in all 'json_parse_ex' calls.
+             (define (use-latest-json-parser file)
+               (substitute* file
+                 (("engine/external/json-parser/json\\.h")
+                  "json-parser/json.h")
+                 (("json_parse_ex\\(&JsonSettings, pFileData, aError\\);")
+                  "json_parse_ex(&JsonSettings,
+                                 pFileData,
+                                 strlen(pFileData),
+                                 aError);")))
+
              ;; Embed path to assets.
              (substitute* "src/engine/shared/storage.cpp"
                (("#define DATA_DIR.*")
@@ -4173,50 +4197,68 @@ small robot living in the nano world, repair its maker.")
                                "\"")))
 
              ;; Bam expects all files to have a recent time stamp.
-             (for-each (lambda (file)
-                         (utime file 1 1))
+             (for-each (cut utime <> 1 1)
                        (find-files "."))
 
              ;; Do not use bundled libraries.
              (substitute* "bam.lua"
-               (("if config.zlib.value == 1 then")
-                "if true then")
-               (("wavpack = .*")
-                "wavpack = {}
-settings.link.libs:Add(\"wavpack\")\n"))
+               (("local json = Compile.+$")
+                "local json = nil
+settings.link.libs:Add(\"jsonparser\")")
+               (("local png = Compile.+$")
+                "local png = nil
+settings.link.libs:Add(\"pnglite\")")
+               (("local wavpack = Compile.+$")
+                "local wavpack = nil
+settings.link.libs:Add(\"wavpack\")")
+               (("if config\\.zlib\\.value == 1")
+                "if config.zlib.value"))
+             (substitute* "src/engine/client/graphics_threaded.cpp"
+               (("engine/external/pnglite/pnglite\\.h")
+                "pnglite.h"))
              (substitute* "src/engine/client/sound.cpp"
-               (("#include <engine/external/wavpack/wavpack.h>")
-                "#include <wavpack/wavpack.h>"))
+               (("engine/external/wavpack/wavpack\\.h")
+                "wavpack/wavpack.h"))
+             (for-each use-latest-json-parser
+                       '("src/game/client/components/countryflags.cpp"
+                         "src/game/client/components/menus_settings.cpp"
+                         "src/game/client/components/skins.cpp"
+                         "src/game/client/localization.cpp"
+                         "src/game/editor/auto_map.h"
+                         "src/game/editor/editor.cpp"))
              #t))
          (replace 'build
            (lambda _
-             (zero? (system* "bam" "-a" "-v" "release"))))
+             (invoke "bam" "-a" "-v" "conf=release")))
          (replace 'install
            (lambda* (#:key outputs #:allow-other-keys)
-             (let* ((out  (assoc-ref outputs "out"))
-                    (bin  (string-append out "/bin"))
-                    (data (string-append out "/share/teeworlds/data")))
-               (mkdir-p bin)
-               (mkdir-p data)
-               (for-each (lambda (file)
-                           (install-file file bin))
-                         '("teeworlds" "teeworlds_srv"))
-               (copy-recursively "data" data)
+             (let* ((arch ,(system->linux-architecture
+                            (or (%current-target-system)
+                                (%current-system))))
+                    (build (string-append "build/" arch "/release/"))
+                    (data-built (string-append build "data/"))
+                    (out (assoc-ref outputs "out"))
+                    (bin (string-append out "/bin/"))
+                    (data (string-append out "/share/teeworlds/data/")))
+               (for-each (cut install-file <> bin)
+                         (map (cut string-append build <>)
+                              '("teeworlds" "teeworlds_srv")))
+               (copy-recursively data-built data)
                #t))))))
-    ;; FIXME: teeworlds bundles the sources of "pnglite", a two-file PNG
-    ;; library without a build system.
     (inputs
      `(("freetype" ,freetype)
        ("glu" ,glu)
+       ("json-parser" ,json-parser)
        ("mesa" ,mesa)
-       ("sdl-union" ,(sdl-union (list sdl
-                                      sdl-mixer
-                                      sdl-image)))
+       ("pnglite" ,pnglite)
+       ("sdl2" ,sdl2)
+       ("sdl2-image" ,sdl2-image)
+       ("sdl2-mixer" ,sdl2-mixer)
        ("wavpack" ,wavpack)
        ("zlib" ,zlib)))
     (native-inputs
      `(("bam" ,bam)
-       ("python" ,python-2)
+       ("python" ,python-wrapper)
        ("pkg-config" ,pkg-config)))
     (home-page "https://www.teeworlds.com")
     (synopsis "2D retro multiplayer shooter game")
diff --git a/gnu/packages/patches/teeworlds-use-latest-wavpack.patch b/gnu/packages/patches/teeworlds-use-latest-wavpack.patch
index e9fd99108..3ad1340d2 100644
--- a/gnu/packages/patches/teeworlds-use-latest-wavpack.patch
+++ b/gnu/packages/patches/teeworlds-use-latest-wavpack.patch
@@ -1,10 +1,20 @@
-Downloaded from https://anonscm.debian.org/cgit/pkg-games/teeworlds.git/plain/debian/patches/new-wavpack.patch.
+Downloaded from https://salsa.debian.org/games-team/teeworlds/raw/master/debian/patches/new-wavpack.patch.
 
-This patch lets us build teeworlds with wavpack 5.1.0.
+From: Markus Koschany <[email-masked]>
+Date: Thu, 25 Oct 2018 20:52:27 +0200
+Subject: new-wavpack
 
+Make wavpack compatible with Debian's version.
+---
+ src/engine/client/sound.cpp | 33 +++++++++++++++------------------
+ src/engine/client/sound.h   |  4 ----
+ 2 files changed, 15 insertions(+), 22 deletions(-)
+
+diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp
+index 048ec24..80de3c5 100644
 --- a/src/engine/client/sound.cpp
 +++ b/src/engine/client/sound.cpp
-@@ -328,17 +328,14 @@ void CSound::RateConvert(int SampleID)
+@@ -325,10 +325,6 @@ void CSound::RateConvert(int SampleID)
  	pSample->m_NumFrames = NumFrames;
  }
  
@@ -12,10 +22,10 @@ This patch lets us build teeworlds with wavpack 5.1.0.
 -{
 -	return io_read(ms_File, pBuffer, Size);
 -}
--
- int CSound::LoadWV(const char *pFilename)
+ 
+ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
  {
- 	CSample *pSample;
+@@ -336,6 +332,8 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
  	int SampleID = -1;
  	char aError[100];
  	WavpackContext *pContext;
@@ -24,17 +34,18 @@ This patch lets us build teeworlds with wavpack 5.1.0.
  
  	// don't waste memory on sound when we are stress testing
  	if(g_Config.m_DbgStress)
-@@ -351,19 +348,23 @@ int CSound::LoadWV(const char *pFilename
- 	if(!m_pStorage)
- 		return -1;
+@@ -349,25 +347,29 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
+ 		return CSampleHandle();
  
+ 	lock_wait(m_SoundLock);
 -	ms_File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL);
 -	if(!ms_File)
 +	File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL, aWholePath, sizeof(aWholePath));
 +	if(!File)
  	{
  		dbg_msg("sound/wv", "failed to open file. filename='%s'", pFilename);
- 		return -1;
+ 		lock_unlock(m_SoundLock);
+ 		return CSampleHandle();
  	}
 +	else
 +	{
@@ -43,7 +54,14 @@ This patch lets us build teeworlds with wavpack 5.1.0.
  
  	SampleID = AllocID();
  	if(SampleID < 0)
- 		return -1;
+ 	{
+-		io_close(ms_File);
+-		ms_File = 0;
++		io_close(File);
++		File = 0;
+ 		lock_unlock(m_SoundLock);
+ 		return CSampleHandle();
+ 	}
  	pSample = &m_aSamples[SampleID];
  
 -	pContext = WavpackOpenFileInput(ReadData, aError);
@@ -51,7 +69,29 @@ This patch lets us build teeworlds with wavpack 5.1.0.
  	if (pContext)
  	{
  		int m_aSamples = WavpackGetNumSamples(pContext);
-@@ -419,9 +420,6 @@ int CSound::LoadWV(const char *pFilename
+@@ -385,8 +387,8 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
+ 		if(pSample->m_Channels > 2)
+ 		{
+ 			dbg_msg("sound/wv", "file is not mono or stereo. filename='%s'", pFilename);
+-			io_close(ms_File);
+-			ms_File = 0;
++			io_close(File);
++			File = 0;
+ 			lock_unlock(m_SoundLock);
+ 			return CSampleHandle();
+ 		}
+@@ -401,8 +403,8 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
+ 		if(BitsPerSample != 16)
+ 		{
+ 			dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", BitsPerSample, pFilename);
+-			io_close(ms_File);
+-			ms_File = 0;
++			io_close(File);
++			File = 0;
+ 			lock_unlock(m_SoundLock);
+ 			return CSampleHandle();
+ 		}
+@@ -429,9 +431,6 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
  		dbg_msg("sound/wv", "failed to open %s: %s", pFilename, aError);
  	}
  
@@ -61,14 +101,16 @@ This patch lets us build teeworlds with wavpack 5.1.0.
  	if(g_Config.m_Debug)
  		dbg_msg("sound/wv", "loaded %s", pFilename);
  
-@@ -527,7 +525,5 @@ void CSound::StopAll()
- 	lock_unlock(m_SoundLock);
+@@ -560,7 +559,5 @@ bool CSound::IsPlaying(CSampleHandle SampleID)
+ 	return Ret;
  }
  
 -IOHANDLE CSound::ms_File = 0;
 -
  IEngineSound *CreateEngineSound() { return new CSound; }
  
+diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h
+index ff357c0..cec2cde 100644
 --- a/src/engine/client/sound.h
 +++ b/src/engine/client/sound.h
 @@ -21,10 +21,6 @@ public:
@@ -81,4 +123,4 @@ This patch lets us build teeworlds with wavpack 5.1.0.
 -
  	virtual bool IsSoundEnabled() { return m_SoundEnabled != 0; }
  
- 	virtual int LoadWV(const char *pFilename);
+ 	virtual CSampleHandle LoadWV(const char *pFilename);
-- 
2.19.1