diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000..8f5c02d
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,70 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    # The branches below must be a subset of the branches above
+    branches: [ master ]
+  schedule:
+    - cron: '32 6 * * 4'
+
+jobs:
+  analyze:
+    name: Analyze
+    runs-on: ubuntu-latest
+    permissions:
+      actions: read
+      contents: read
+      security-events: write
+
+    strategy:
+      fail-fast: false
+      matrix:
+        language: [ 'go' ]
+        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+        # Learn more about CodeQL language support at https://git.io/codeql-language-support
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout@v2
+
+    # Initializes the CodeQL tools for scanning.
+    - name: Initialize CodeQL
+      uses: github/codeql-action/init@v1
+      with:
+        languages: ${{ matrix.language }}
+        # If you wish to specify custom queries, you can do so here or in a config file.
+        # By default, queries listed here will override any specified in a config file.
+        # Prefix the list here with "+" to use these queries and those in the config file.
+        # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
+    # If this step fails, then you should remove it and run the build manually (see below)
+    - name: Autobuild
+      uses: github/codeql-action/autobuild@v1
+
+    # ℹ️ Command-line programs to run using the OS shell.
+    # 📚 https://git.io/JvXDl
+
+    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+    #    and modify them (or add more) to build your code if your project
+    #    uses a compiled language
+
+    #- run: |
+    #   make bootstrap
+    #   make release
+
+    - name: Perform CodeQL Analysis
+      uses: github/codeql-action/analyze@v1
diff --git a/.gitignore b/.gitignore
index e3c2fc2..eb3d5f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,6 @@ cmd/xb/xb
 
 # default compression test file
 enwik8*
+
+# file generated by example
+example.xz
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 58ebdc1..009b848 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014-2016  Ulrich Kunitz
+Copyright (c) 2014-2021  Ulrich Kunitz
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/README.md b/README.md
index 0a2dc82..5547185 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,10 @@ func main() {
 }
 ```
 
+## Documentation
+
+You can find the full documentation at [pkg.go.dev](https://pkg.go.dev/github.com/ulikunitz/xz).
+
 ## Using the gxz compression tool
 
 The package includes a gxz command line utility for compression and
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..5f7ec01
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,10 @@
+# Security Policy
+
+## Supported Versions
+
+Currently the last minor version v0.5.x is supported.
+
+## Reporting a Vulnerability
+
+Report a vulnerability by creating a Github issue at
+<https://github.com/ulikunitz/xz/issues>. Expect a response in a week.
diff --git a/TODO.md b/TODO.md
index 1be3bb8..594e0c7 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,22 +1,24 @@
 # TODO list
 
+## Release v0.5.x
+
+1. Support check flag in gxz command.
+
 ## Release v0.6
 
 1. Review encoder and check for lzma improvements under xz.
 2. Fix binary tree matcher.
-3. Compare compression ratio with xz tool using comparable parameters
-   and optimize parameters
-4. Do some optimizations
-    - rename operation action and make it a simple type of size 8
-    - make maxMatches, wordSize parameters
-    - stop searching after a certain length is found (parameter sweetLen)
+3. Compare compression ratio with xz tool using comparable parameters and optimize parameters
+4. rename operation action and make it a simple type of size 8
+5. make maxMatches, wordSize parameters
+6. stop searching after a certain length is found (parameter sweetLen)
 
 ## Release v0.7
 
 1. Optimize code
 2. Do statistical analysis to get linear presets.
 3. Test sync.Pool compatability for xz and lzma Writer and Reader
-3. Fuzz optimized code.
+4. Fuzz optimized code.
 
 ## Release v0.8
 
@@ -40,52 +42,90 @@
 
 ## Package lzma
 
-### Release v0.6
-
-- Rewrite Encoder into a simple greedy one-op-at-a-time encoder
-  including
-    + simple scan at the dictionary head for the same byte
-    + use the killer byte (requiring matches to get longer, the first
-      test should be the byte that would make the match longer)
+### v0.6
 
+* Rewrite Encoder into a simple greedy one-op-at-a-time encoder including
+  * simple scan at the dictionary head for the same byte
+  * use the killer byte (requiring matches to get longer, the first test should be the byte that would make the match longer)
 
 ## Optimizations
 
-- There may be a lot of false sharing in lzma.State; check whether this
-  can be improved by reorganizing the internal structure of it.
-- Check whether batching encoding and decoding improves speed.
+* There may be a lot of false sharing in lzma. State; check whether this  can be improved by reorganizing the internal structure of it.
+
+* Check whether batching encoding and decoding improves speed.
 
 ### DAG optimizations
 
-- Use full buffer to create minimal bit-length above range encoder.
-- Might be too slow (see v0.4)
+* Use full buffer to create minimal bit-length above range encoder.
+* Might be too slow (see v0.4)
 
 ### Different match finders
 
-- hashes with 2, 3 characters additional to 4 characters
-- binary trees with 2-7 characters (uint64 as key, use uint32 as
+* hashes with 2, 3 characters additional to 4 characters
+* binary trees with 2-7 characters (uint64 as key, use uint32 as
+
   pointers into a an array)
-- rb-trees with 2-7 characters (uint64 as key, use uint32 as pointers
+
+* rb-trees with 2-7 characters (uint64 as key, use uint32 as pointers
+
   into an array with bit-steeling for the colors)
 
 ## Release Procedure
 
-- execute goch -l for all packages; probably with lower param like 0.5.
-- check orthography with gospell
-- Write release notes in doc/relnotes.
-- Update README.md
-- xb copyright . in xz directory to ensure all new files have Copyright
-  header
-- VERSION=<version> go generate github.com/ulikunitz/xz/... to update
-  version files
-- Execute test for Linux/amd64, Linux/x86 and Windows/amd64.
-- Update TODO.md - write short log entry
-- git checkout master && git merge dev
-- git tag -a <version>
-- git push
+* execute goch -l for all packages; probably with lower param like 0.5.
+* check orthography with gospell
+* Write release notes in doc/relnotes.
+* Update README.md
+* xb copyright . in xz directory to ensure all new files have Copyright header
+* `VERSION=<version> go generate github.com/ulikunitz/xz/...` to update version files
+* Execute test for Linux/amd64, Linux/x86 and Windows/amd64.
+* Update TODO.md - write short log entry
+* `git checkout master && git merge dev`
+* `git tag -a <version>`
+* `git push`
 
 ## Log
 
+### 2021-02-02
+
+Mituo Heijo has fuzzed xz and found a bug in the function readIndexBody. The
+function allocated a slice of records immediately after reading the value
+without further checks. Since the number has been too large the make function
+did panic. The fix is to check the number against the expected number of records
+before allocating the records.
+
+### 2020-12-17
+
+Release v0.5.9 fixes warnings, a typo and adds SECURITY.md.
+
+One fix is interesting.
+
+```go
+const (
+  a byte = 0x1
+  b      = 0x2
+)
+```
+
+The constants a and b don't have the same type. Correct is
+
+```go
+const (
+  a byte = 0x1
+  b byte = 0x2
+)
+```
+
+### 2020-08-19
+
+Release v0.5.8 fixes issue
+[issue #35](https://github.com/ulikunitz/xz/issues/35).
+
+### 2020-02-24
+
+Release v0.5.7 supports the check-ID None and fixes
+[issue #27](https://github.com/ulikunitz/xz/issues/27).
+
 ### 2019-02-20
 
 Release v0.5.6 supports the go.mod file.
@@ -194,8 +234,8 @@ MININT.
 
 ### 2015-06-04
 
-It has been a productive day. I improved the interface of lzma.Reader
-and lzma.Writer and fixed the error handling.
+It has been a productive day. I improved the interface of lzma. Reader
+and lzma. Writer and fixed the error handling.
 
 ### 2015-06-01
 
@@ -246,7 +286,7 @@ needed anymore.
 
 However I will implement a ReaderState and WriterState type to use
 static typing to ensure the right State object is combined with the
-right lzbase.Reader and lzbase.Writer.
+right lzbase. Reader and lzbase. Writer.
 
 As a start I have implemented ReaderState and WriterState to ensure
 that the state for reading is only used by readers and WriterState only
@@ -268,11 +308,11 @@ old lzma package has been completely removed.
 
 ### 2015-04-05
 
-Implemented lzma.Reader and tested it.
+Implemented lzma. Reader and tested it.
 
 ### 2015-04-04
 
-Implemented baseReader by adapting code form lzma.Reader.
+Implemented baseReader by adapting code form lzma. Reader.
 
 ### 2015-04-03
 
@@ -288,7 +328,7 @@ However in Francesco Campoy's presentation "Go for Javaneros
 (Javaïstes?)" is the the idea that using an embedded field E, all the
 methods of E will be defined on T. If E is an interface T satisfies E.
 
-https://talks.golang.org/2014/go4java.slide#51
+<https://talks.golang.org/2014/go4java.slide#51>
 
 I have never used this, but it seems to be a cool idea.
 
@@ -313,11 +353,11 @@ and the opCodec.
 
 1. Implemented simple lzmago tool
 2. Tested tool against large 4.4G file
-    - compression worked correctly; tested decompression with lzma
-    - decompression hits a full buffer condition
+   * compression worked correctly; tested decompression with lzma
+   * decompression hits a full buffer condition
 3. Fixed a bug in the compressor and wrote a test for it
 4. Executed full cycle for 4.4 GB file; performance can be improved ;-)
 
 ### 2015-01-11
 
-- Release v0.2 because of the working LZMA encoder and decoder
+* Release v0.2 because of the working LZMA encoder and decoder
diff --git a/bits.go b/bits.go
index fadc1a5..e48450c 100644
--- a/bits.go
+++ b/bits.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -54,6 +54,8 @@ var errOverflowU64 = errors.New("xz: uvarint overflows 64-bit unsigned integer")
 
 // readUvarint reads a uvarint from the given byte reader.
 func readUvarint(r io.ByteReader) (x uint64, n int, err error) {
+	const maxUvarintLen = 10
+
 	var s uint
 	i := 0
 	for {
@@ -62,8 +64,11 @@ func readUvarint(r io.ByteReader) (x uint64, n int, err error) {
 			return x, i, err
 		}
 		i++
+		if i > maxUvarintLen {
+			return x, i, errOverflowU64
+		}
 		if b < 0x80 {
-			if i > 10 || i == 10 && b > 1 {
+			if i == maxUvarintLen && b > 1 {
 				return x, i, errOverflowU64
 			}
 			return x | uint64(b)<<s, i, nil
diff --git a/bits_test.go b/bits_test.go
index 68dac96..f07f4e0 100644
--- a/bits_test.go
+++ b/bits_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -31,3 +31,14 @@ func TestUvarint(t *testing.T) {
 		}
 	}
 }
+
+func TestUvarIntCVE_2020_16845(t *testing.T) {
+	var a = []byte{0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+		0x88, 0x89, 0x8a, 0x8b}
+
+	r := bytes.NewReader(a)
+	_, _, err := readUvarint(r)
+	if err != errOverflowU64 {
+		t.Fatalf("readUvarint overflow not detected")
+	}
+}
diff --git a/cmd/gxz/file.go b/cmd/gxz/file.go
index a0a9d30..48bfa0a 100644
--- a/cmd/gxz/file.go
+++ b/cmd/gxz/file.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/cmd/gxz/licenses.go b/cmd/gxz/licenses.go
index 956acc4..c05c5bf 100644
--- a/cmd/gxz/licenses.go
+++ b/cmd/gxz/licenses.go
@@ -28,7 +28,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 `
-const xzLicense = `Copyright (c) 2014-2019  Ulrich Kunitz
+const xzLicense = `Copyright (c) 2014-2021  Ulrich Kunitz
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/cmd/gxz/main.go b/cmd/gxz/main.go
index 482b78f..63bd181 100644
--- a/cmd/gxz/main.go
+++ b/cmd/gxz/main.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/cmd/gxz/version.go b/cmd/gxz/version.go
index 3543870..d7ecbda 100644
--- a/cmd/gxz/version.go
+++ b/cmd/gxz/version.go
@@ -1,3 +1,3 @@
 package main
 
-const version = "v0.5.6"
+const version = "v0.5.10"
diff --git a/cmd/xb/cat.go b/cmd/xb/cat.go
index 2d75af7..336457b 100644
--- a/cmd/xb/cat.go
+++ b/cmd/xb/cat.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/cmd/xb/copyright.go b/cmd/xb/copyright.go
index 6d29450..92664f9 100644
--- a/cmd/xb/copyright.go
+++ b/cmd/xb/copyright.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -28,7 +28,7 @@ func crUsage(w io.Writer) {
 }
 
 const copyrightText = `
-Copyright 2014-2019 Ulrich Kunitz. All rights reserved.
+Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 Use of this source code is governed by a BSD-style
 license that can be found in the LICENSE file.
 `
diff --git a/cmd/xb/main.go b/cmd/xb/main.go
index f5b4cf0..465b937 100644
--- a/cmd/xb/main.go
+++ b/cmd/xb/main.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/cmd/xb/version-file.go b/cmd/xb/version-file.go
index 0f959de..5422e21 100644
--- a/cmd/xb/version-file.go
+++ b/cmd/xb/version-file.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/cmd/xb/version.go b/cmd/xb/version.go
index 3543870..d7ecbda 100644
--- a/cmd/xb/version.go
+++ b/cmd/xb/version.go
@@ -1,3 +1,3 @@
 package main
 
-const version = "v0.5.6"
+const version = "v0.5.10"
diff --git a/crc.go b/crc.go
index b44dca9..a5c57fb 100644
--- a/crc.go
+++ b/crc.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/debian/changelog b/debian/changelog
index ab801a2..fd438b7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+golang-github-ulikunitz-xz (0.5.10+git20211217.1.ae23369-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+  * Drop patch 0001-CVE-2021-29482.patch, present upstream.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sun, 20 Mar 2022 07:32:18 -0000
+
 golang-github-ulikunitz-xz (0.5.6-2) unstable; urgency=medium
 
   * Team upload.
diff --git a/debian/patches/0001-CVE-2021-29482.patch b/debian/patches/0001-CVE-2021-29482.patch
deleted file mode 100644
index 50d5cca..0000000
--- a/debian/patches/0001-CVE-2021-29482.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-From: Ulrich Kunitz <ulikunitz@users.noreply.github.com>
-Date: Wed, 19 Aug 2020 18:04:10 +0200
-Subject: CVE-2021-29482
-
-Origin: backport, https://github.com/ulikunitz/xz/commit/69c6093c7b2397b923acf82cb378f55ab2652b9b
----
- bits.go      |  7 ++++++-
- bits_test.go | 11 +++++++++++
- 2 files changed, 17 insertions(+), 1 deletion(-)
-
-diff --git a/bits.go b/bits.go
-index fadc1a5..87d4623 100644
---- a/bits.go
-+++ b/bits.go
-@@ -54,6 +54,8 @@ var errOverflowU64 = errors.New("xz: uvarint overflows 64-bit unsigned integer")
- 
- // readUvarint reads a uvarint from the given byte reader.
- func readUvarint(r io.ByteReader) (x uint64, n int, err error) {
-+	const maxUvarintLen = 10
-+
- 	var s uint
- 	i := 0
- 	for {
-@@ -62,8 +64,11 @@ func readUvarint(r io.ByteReader) (x uint64, n int, err error) {
- 			return x, i, err
- 		}
- 		i++
-+		if i > maxUvarintLen {
-+			return x, i, errOverflowU64
-+		}
- 		if b < 0x80 {
--			if i > 10 || i == 10 && b > 1 {
-+			if i == maxUvarintLen && b > 1 {
- 				return x, i, errOverflowU64
- 			}
- 			return x | uint64(b)<<s, i, nil
-diff --git a/bits_test.go b/bits_test.go
-index 68dac96..07ffc1f 100644
---- a/bits_test.go
-+++ b/bits_test.go
-@@ -31,3 +31,14 @@ func TestUvarint(t *testing.T) {
- 		}
- 	}
- }
-+
-+func TestUvarIntCVE_2020_16845(t *testing.T) {
-+	var a = []byte{0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-+		0x88, 0x89, 0x8a, 0x8b}
-+
-+	r := bytes.NewReader(a)
-+	_, _, err := readUvarint(r)
-+	if err != errOverflowU64 {
-+		t.Fatalf("readUvarint overflow not detected")
-+	}
-+}
diff --git a/debian/patches/series b/debian/patches/series
index 894d68a..e69de29 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +0,0 @@
-0001-CVE-2021-29482.patch
diff --git a/doc/relnotes/release-v0.5.10.md b/doc/relnotes/release-v0.5.10.md
new file mode 100644
index 0000000..93abcfd
--- /dev/null
+++ b/doc/relnotes/release-v0.5.10.md
@@ -0,0 +1,4 @@
+# Release Notes v0.5.10
+
+This release fixes issue #40. Many thanks to Github user Misuo Heijo for fuzzing
+the xz module.
diff --git a/doc/relnotes/release-v0.5.7.md b/doc/relnotes/release-v0.5.7.md
new file mode 100644
index 0000000..bf55916
--- /dev/null
+++ b/doc/relnotes/release-v0.5.7.md
@@ -0,0 +1,7 @@
+# Release Notes v0.5.7
+
+This release fixes issue #27 "Checksum None is valid" by supporting the
+check-ID None.
+
+Many thanks to [blacktop](https://github.com/blacktop) for reporting the
+bug.
diff --git a/doc/relnotes/release-v0.5.8.md b/doc/relnotes/release-v0.5.8.md
new file mode 100644
index 0000000..f928427
--- /dev/null
+++ b/doc/relnotes/release-v0.5.8.md
@@ -0,0 +1,8 @@
+# Release Notes v0.5.8
+
+This release fixes the security issue #35. The readUvarint function
+would run infinitely given specific input. The function is now
+terminating if more than 10 bytes of input have been read. The behavior
+is tested.
+
+Many thanks to Github user 0xdecaf for reporting the issue.
diff --git a/doc/relnotes/release-v0.5.9.md b/doc/relnotes/release-v0.5.9.md
new file mode 100644
index 0000000..4ee593c
--- /dev/null
+++ b/doc/relnotes/release-v0.5.9.md
@@ -0,0 +1,8 @@
+# Release Notes v0.5.9
+
+This release fixes:
+
+    - all staticcheck issues in the public repositories.
+    - fixes wrong const type definitions; thanks Matt LaPlante
+    - fixes a typo; Michael Vetter
+    - adds a SECURITY.md file
diff --git a/example.go b/example.go
index 855e60a..fbe6a1d 100644
--- a/example.go
+++ b/example.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/example_test.go b/example_test.go
new file mode 100644
index 0000000..76ee687
--- /dev/null
+++ b/example_test.go
@@ -0,0 +1,49 @@
+package xz_test
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"log"
+	"os"
+
+	"github.com/ulikunitz/xz"
+)
+
+func ExampleReader() {
+	f, err := os.Open("fox.xz")
+	if err != nil {
+		log.Fatalf("os.Open(%q) error %s", "fox.xz", err)
+	}
+	defer f.Close()
+	r, err := xz.NewReader(bufio.NewReader(f))
+	if err != nil {
+		log.Fatalf("xz.NewReader(f) error %s", err)
+	}
+	if _, err = io.Copy(os.Stdout, r); err != nil {
+		log.Fatalf("io.Copy error %s", err)
+	}
+	// Output:
+	// The quick brown fox jumps over the lazy dog.
+}
+
+func ExampleWriter() {
+	f, err := os.Create("example.xz")
+	if err != nil {
+		log.Fatalf("os.Open(%q) error %s", "example.xz", err)
+	}
+	defer f.Close()
+	w, err := xz.NewWriter(f)
+	if err != nil {
+		log.Fatalf("xz.NewWriter(f) error %s", err)
+	}
+	defer w.Close()
+	_, err = fmt.Fprintln(w, "The brown fox jumps over the lazy dog.")
+	if err != nil {
+		log.Fatalf("fmt.Fprintln error %s", err)
+	}
+	if err = w.Close(); err != nil {
+		log.Fatalf("w.Close() error %s", err)
+	}
+	// Output:
+}
diff --git a/format.go b/format.go
index 798159c..c98c12d 100644
--- a/format.go
+++ b/format.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -46,9 +46,10 @@ const HeaderLen = 12
 
 // Constants for the checksum methods supported by xz.
 const (
+	None   byte = 0x0
 	CRC32  byte = 0x1
-	CRC64       = 0x4
-	SHA256      = 0xa
+	CRC64  byte = 0x4
+	SHA256 byte = 0xa
 )
 
 // errInvalidFlags indicates that flags are invalid.
@@ -58,7 +59,7 @@ var errInvalidFlags = errors.New("xz: invalid flags")
 // invalid.
 func verifyFlags(flags byte) error {
 	switch flags {
-	case CRC32, CRC64, SHA256:
+	case None, CRC32, CRC64, SHA256:
 		return nil
 	default:
 		return errInvalidFlags
@@ -67,6 +68,7 @@ func verifyFlags(flags byte) error {
 
 // flagstrings maps flag values to strings.
 var flagstrings = map[byte]string{
+	None:   "None",
 	CRC32:  "CRC-32",
 	CRC64:  "CRC-64",
 	SHA256: "SHA-256",
@@ -85,6 +87,8 @@ func flagString(flags byte) string {
 // hash method encoded in flags.
 func newHashFunc(flags byte) (newHash func() hash.Hash, err error) {
 	switch flags {
+	case None:
+		newHash = newNoneHash
 	case CRC32:
 		newHash = newCRC32
 	case CRC64:
@@ -565,22 +569,6 @@ func readFilters(r io.Reader, count int) (filters []filter, err error) {
 	return []filter{f}, err
 }
 
-// writeFilters writes the filters.
-func writeFilters(w io.Writer, filters []filter) (n int, err error) {
-	for _, f := range filters {
-		p, err := f.MarshalBinary()
-		if err != nil {
-			return n, err
-		}
-		k, err := w.Write(p)
-		n += k
-		if err != nil {
-			return n, err
-		}
-	}
-	return n, nil
-}
-
 /*** Index ***/
 
 // record describes a block in the xz file index.
@@ -674,7 +662,7 @@ func writeIndex(w io.Writer, index []record) (n int64, err error) {
 
 // readIndexBody reads the index from the reader. It assumes that the
 // index indicator has already been read.
-func readIndexBody(r io.Reader) (records []record, n int64, err error) {
+func readIndexBody(r io.Reader, expectedRecordLen int) (records []record, n int64, err error) {
 	crc := crc32.NewIEEE()
 	// index indicator
 	crc.Write([]byte{0})
@@ -691,6 +679,11 @@ func readIndexBody(r io.Reader) (records []record, n int64, err error) {
 	if recLen < 0 || uint64(recLen) != u {
 		return nil, n, errors.New("xz: record number overflow")
 	}
+	if recLen != expectedRecordLen {
+		return nil, n, fmt.Errorf(
+			"xz: index length is %d; want %d",
+			recLen, expectedRecordLen)
+	}
 
 	// list of records
 	records = make([]record, recLen)
diff --git a/format_test.go b/format_test.go
index 693cd30..556a608 100644
--- a/format_test.go
+++ b/format_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -85,7 +85,7 @@ func TestIndex(t *testing.T) {
 		t.Fatalf("indicator %d; want %d", c, 0)
 	}
 
-	g, m, err := readIndexBody(&buf)
+	g, m, err := readIndexBody(&buf, len(records))
 	if err != nil {
 		for i, r := range g {
 			t.Logf("records[%d] %v", i, r)
diff --git a/fox-check-none.xz b/fox-check-none.xz
new file mode 100644
index 0000000..46043f7
Binary files /dev/null and b/fox-check-none.xz differ
diff --git a/go.mod b/go.mod
index 9e5eea2..330b675 100644
--- a/go.mod
+++ b/go.mod
@@ -1 +1,3 @@
 module github.com/ulikunitz/xz
+
+go 1.12
diff --git a/internal/gflag/flag.go b/internal/gflag/flag.go
index eef9eba..17e2647 100644
--- a/internal/gflag/flag.go
+++ b/internal/gflag/flag.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/gflag/flag_test.go b/internal/gflag/flag_test.go
index 7ef2694..cba055b 100644
--- a/internal/gflag/flag_test.go
+++ b/internal/gflag/flag_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/hash/cyclic_poly.go b/internal/hash/cyclic_poly.go
index a328878..f723cf2 100644
--- a/internal/hash/cyclic_poly.go
+++ b/internal/hash/cyclic_poly.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/hash/cyclic_poly_test.go b/internal/hash/cyclic_poly_test.go
index dac0d72..9213e9f 100644
--- a/internal/hash/cyclic_poly_test.go
+++ b/internal/hash/cyclic_poly_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/hash/doc.go b/internal/hash/doc.go
index f99ec22..cc60a6b 100644
--- a/internal/hash/doc.go
+++ b/internal/hash/doc.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/hash/rabin_karp.go b/internal/hash/rabin_karp.go
index 58635b1..c643291 100644
--- a/internal/hash/rabin_karp.go
+++ b/internal/hash/rabin_karp.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/hash/rabin_karp_test.go b/internal/hash/rabin_karp_test.go
index b017c56..45d47d2 100644
--- a/internal/hash/rabin_karp_test.go
+++ b/internal/hash/rabin_karp_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/hash/roller.go b/internal/hash/roller.go
index ab6a19c..f1de88b 100644
--- a/internal/hash/roller.go
+++ b/internal/hash/roller.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/randtxt/englm3.go b/internal/randtxt/englm3.go
index 0d4caa6..bc3da9f 100644
--- a/internal/randtxt/englm3.go
+++ b/internal/randtxt/englm3.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/randtxt/groupreader.go b/internal/randtxt/groupreader.go
index ac02c87..5dd173c 100644
--- a/internal/randtxt/groupreader.go
+++ b/internal/randtxt/groupreader.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/randtxt/probs.go b/internal/randtxt/probs.go
index 6bca03b..6d91085 100644
--- a/internal/randtxt/probs.go
+++ b/internal/randtxt/probs.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/randtxt/probs_test.go b/internal/randtxt/probs_test.go
index 1b72ddc..5b4c461 100644
--- a/internal/randtxt/probs_test.go
+++ b/internal/randtxt/probs_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/term/ioctl_bsd.go b/internal/term/ioctl_bsd.go
index 8e3b982..058b648 100644
--- a/internal/term/ioctl_bsd.go
+++ b/internal/term/ioctl_bsd.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/term/ioctl_linux.go b/internal/term/ioctl_linux.go
index aefdb38..9a17d07 100644
--- a/internal/term/ioctl_linux.go
+++ b/internal/term/ioctl_linux.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/term/isterminal.go b/internal/term/isterminal.go
index f7f9f1d..a44bd2b 100644
--- a/internal/term/isterminal.go
+++ b/internal/term/isterminal.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/term/isterminal_windows.go b/internal/term/isterminal_windows.go
index 3e09432..9d9cb7a 100644
--- a/internal/term/isterminal_windows.go
+++ b/internal/term/isterminal_windows.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/internal/xlog/xlog.go b/internal/xlog/xlog.go
index 0ba45e8..6c20c77 100644
--- a/internal/xlog/xlog.go
+++ b/internal/xlog/xlog.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/bintree.go b/lzma/bintree.go
index a781bd1..2a7bd19 100644
--- a/lzma/bintree.go
+++ b/lzma/bintree.go
@@ -1,14 +1,11 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package lzma
 
 import (
-	"bufio"
 	"errors"
-	"fmt"
-	"io"
 	"unicode"
 )
 
@@ -349,6 +346,7 @@ func dumpX(x uint32) string {
 	return string(a)
 }
 
+/*
 // dumpNode writes a representation of the node v into the io.Writer.
 func (t *binTree) dumpNode(w io.Writer, v uint32, indent int) {
 	if v == null {
@@ -377,6 +375,7 @@ func (t *binTree) dump(w io.Writer) error {
 	t.dumpNode(bw, t.root, 0)
 	return bw.Flush()
 }
+*/
 
 func (t *binTree) distance(v uint32) int {
 	dist := int(t.front) - int(v)
diff --git a/lzma/bintree_test.go b/lzma/bintree_test.go
index beae29a..d0dd13f 100644
--- a/lzma/bintree_test.go
+++ b/lzma/bintree_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/bitops.go b/lzma/bitops.go
index e9bab01..d2c07e8 100644
--- a/lzma/bitops.go
+++ b/lzma/bitops.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -18,6 +18,7 @@ var ntz32Table = [32]int8{
 	30, 17, 8, 14, 29, 13, 28, 27,
 }
 
+/*
 // ntz32 computes the number of trailing zeros for an unsigned 32-bit integer.
 func ntz32(x uint32) int {
 	if x == 0 {
@@ -26,6 +27,7 @@ func ntz32(x uint32) int {
 	x = (x & -x) * ntz32Const
 	return int(ntz32Table[x>>27])
 }
+*/
 
 // nlz32 computes the number of leading zeros for an unsigned 32-bit integer.
 func nlz32(x uint32) int {
diff --git a/lzma/breader.go b/lzma/breader.go
index 5350d81..939be88 100644
--- a/lzma/breader.go
+++ b/lzma/breader.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/buffer.go b/lzma/buffer.go
index 50e0b6d..2761de5 100644
--- a/lzma/buffer.go
+++ b/lzma/buffer.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/buffer_test.go b/lzma/buffer_test.go
index a055e76..cad23ad 100644
--- a/lzma/buffer_test.go
+++ b/lzma/buffer_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/bytewriter.go b/lzma/bytewriter.go
index a3696ba..040874c 100644
--- a/lzma/bytewriter.go
+++ b/lzma/bytewriter.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/decoder.go b/lzma/decoder.go
index 16e14db..cbb943a 100644
--- a/lzma/decoder.go
+++ b/lzma/decoder.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -200,7 +200,7 @@ func (d *decoder) decompress() error {
 		op, err := d.readOp()
 		switch err {
 		case nil:
-			break
+			// break
 		case errEOS:
 			d.eos = true
 			if !d.rd.possiblyAtEnd() {
diff --git a/lzma/decoder_test.go b/lzma/decoder_test.go
index 7a80ebb..bbe4f29 100644
--- a/lzma/decoder_test.go
+++ b/lzma/decoder_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/decoderdict.go b/lzma/decoderdict.go
index 564a12b..8cd616e 100644
--- a/lzma/decoderdict.go
+++ b/lzma/decoderdict.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -126,10 +126,3 @@ func (d *decoderDict) Available() int { return d.buf.Available() }
 
 // Read reads data from the buffer contained in the decoder dictionary.
 func (d *decoderDict) Read(p []byte) (n int, err error) { return d.buf.Read(p) }
-
-// Buffered returns the number of bytes currently buffered in the
-// decoder dictionary.
-func (d *decoderDict) buffered() int { return d.buf.Buffered() }
-
-// Peek gets data from the buffer without advancing the rear index.
-func (d *decoderDict) peek(p []byte) (n int, err error) { return d.buf.Peek(p) }
diff --git a/lzma/decoderdict_test.go b/lzma/decoderdict_test.go
index 95508ac..b24034f 100644
--- a/lzma/decoderdict_test.go
+++ b/lzma/decoderdict_test.go
@@ -1,28 +1,13 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package lzma
 
 import (
-	"fmt"
 	"testing"
 )
 
-func peek(d *decoderDict) []byte {
-	p := make([]byte, d.buffered())
-	k, err := d.peek(p)
-	if err != nil {
-		panic(fmt.Errorf("peek: "+
-			"Read returned unexpected error %s", err))
-	}
-	if k != len(p) {
-		panic(fmt.Errorf("peek: "+
-			"Read returned %d; wanted %d", k, len(p)))
-	}
-	return p
-}
-
 func TestNewDecoderDict(t *testing.T) {
 	if _, err := newDecoderDict(0); err == nil {
 		t.Fatalf("no error for zero dictionary capacity")
diff --git a/lzma/directcodec.go b/lzma/directcodec.go
index e08eb98..20b256a 100644
--- a/lzma/directcodec.go
+++ b/lzma/directcodec.go
@@ -1,24 +1,13 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package lzma
 
-import "fmt"
-
 // directCodec allows the encoding and decoding of values with a fixed number
 // of bits. The number of bits must be in the range [1,32].
 type directCodec byte
 
-// makeDirectCodec creates a directCodec. The function panics if the number of
-// bits is not in the range [1,32].
-func makeDirectCodec(bits int) directCodec {
-	if !(1 <= bits && bits <= 32) {
-		panic(fmt.Errorf("bits=%d out of range", bits))
-	}
-	return directCodec(bits)
-}
-
 // Bits returns the number of bits supported by this codec.
 func (dc directCodec) Bits() int {
 	return int(dc)
diff --git a/lzma/distcodec.go b/lzma/distcodec.go
index b053a2d..60ed9ae 100644
--- a/lzma/distcodec.go
+++ b/lzma/distcodec.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -20,8 +20,6 @@ const (
 	posSlotBits = 6
 	// number of align bits
 	alignBits = 4
-	// maximum position slot
-	maxPosSlot = 63
 )
 
 // distCodec provides encoding and decoding of distance values.
@@ -45,20 +43,6 @@ func (dc *distCodec) deepcopy(src *distCodec) {
 	dc.alignCodec.deepcopy(&src.alignCodec)
 }
 
-// distBits returns the number of bits required to encode dist.
-func distBits(dist uint32) int {
-	if dist < startPosModel {
-		return 6
-	}
-	// slot s > 3, dist d
-	// s = 2(bits(d)-1) + bit(d, bits(d)-2)
-	// s>>1 = bits(d)-1
-	// bits(d) = 32-nlz32(d)
-	// s>>1=31-nlz32(d)
-	// n = 5 + (s>>1) = 36 - nlz32(d)
-	return 36 - nlz32(dist)
-}
-
 // newDistCodec creates a new distance codec.
 func (dc *distCodec) init() {
 	for i := range dc.posSlotCodecs {
diff --git a/lzma/encoder.go b/lzma/encoder.go
index fe1900a..5ed057a 100644
--- a/lzma/encoder.go
+++ b/lzma/encoder.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/encoder_test.go b/lzma/encoder_test.go
index 4cb3231..4fcf099 100644
--- a/lzma/encoder_test.go
+++ b/lzma/encoder_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/encoderdict.go b/lzma/encoderdict.go
index 9d0fbc7..056f897 100644
--- a/lzma/encoderdict.go
+++ b/lzma/encoderdict.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -19,7 +19,7 @@ type matcher interface {
 }
 
 // encoderDict provides the dictionary of the encoder. It includes an
-// addtional buffer atop of the actual dictionary.
+// additional buffer atop of the actual dictionary.
 type encoderDict struct {
 	buf      buffer
 	m        matcher
diff --git a/lzma/hashtable.go b/lzma/hashtable.go
index d786a97..0fb7910 100644
--- a/lzma/hashtable.go
+++ b/lzma/hashtable.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/hashtable_test.go b/lzma/hashtable_test.go
index 1c95bd6..4d4a9b0 100644
--- a/lzma/hashtable_test.go
+++ b/lzma/hashtable_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/header.go b/lzma/header.go
index bc70896..04276c8 100644
--- a/lzma/header.go
+++ b/lzma/header.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/header2.go b/lzma/header2.go
index ac6a71a..be54dd8 100644
--- a/lzma/header2.go
+++ b/lzma/header2.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -264,7 +264,7 @@ type chunkState byte
 // state
 const (
 	start chunkState = 'S'
-	stop             = 'T'
+	stop  chunkState = 'T'
 )
 
 // errors for the chunk state handling
diff --git a/lzma/header2_test.go b/lzma/header2_test.go
index ecaac3a..fb6a36b 100644
--- a/lzma/header2_test.go
+++ b/lzma/header2_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/header_test.go b/lzma/header_test.go
index a28da3c..91607c7 100644
--- a/lzma/header_test.go
+++ b/lzma/header_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/lengthcodec.go b/lzma/lengthcodec.go
index e517730..6e0edfc 100644
--- a/lzma/lengthcodec.go
+++ b/lzma/lengthcodec.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -56,19 +56,6 @@ func (lc *lengthCodec) init() {
 	lc.high = makeTreeCodec(8)
 }
 
-// lBits gives the number of bits used for the encoding of the l value
-// provided to the range encoder.
-func lBits(l uint32) int {
-	switch {
-	case l < 8:
-		return 4
-	case l < 16:
-		return 5
-	default:
-		return 10
-	}
-}
-
 // Encode encodes the length offset. The length offset l can be compute by
 // subtracting minMatchLen (2) from the actual length.
 //
diff --git a/lzma/literalcodec.go b/lzma/literalcodec.go
index c949d6e..0bfc763 100644
--- a/lzma/literalcodec.go
+++ b/lzma/literalcodec.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -123,10 +123,3 @@ const (
 	minLP = 0
 	maxLP = 4
 )
-
-// minState and maxState define a range for the state values stored in
-// the State values.
-const (
-	minState = 0
-	maxState = 11
-)
diff --git a/lzma/matchalgorithm.go b/lzma/matchalgorithm.go
index 4a244eb..96ebda0 100644
--- a/lzma/matchalgorithm.go
+++ b/lzma/matchalgorithm.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/operation.go b/lzma/operation.go
index 733bb99..026ce48 100644
--- a/lzma/operation.go
+++ b/lzma/operation.go
@@ -1,11 +1,10 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package lzma
 
 import (
-	"errors"
 	"fmt"
 	"unicode"
 )
@@ -24,30 +23,6 @@ type match struct {
 	n int
 }
 
-// verify checks whether the match is valid. If that is not the case an
-// error is returned.
-func (m match) verify() error {
-	if !(minDistance <= m.distance && m.distance <= maxDistance) {
-		return errors.New("distance out of range")
-	}
-	if !(1 <= m.n && m.n <= maxMatchLen) {
-		return errors.New("length out of range")
-	}
-	return nil
-}
-
-// l return the l-value for the match, which is the difference of length
-// n and 2.
-func (m match) l() uint32 {
-	return uint32(m.n - minMatchLen)
-}
-
-// dist returns the dist value for the match, which is one less of the
-// distance stored in the match.
-func (m match) dist() uint32 {
-	return uint32(m.distance - minDistance)
-}
-
 // Len returns the number of bytes matched.
 func (m match) Len() int {
 	return m.n
diff --git a/lzma/prob.go b/lzma/prob.go
index 24d50ec..9a2648e 100644
--- a/lzma/prob.go
+++ b/lzma/prob.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/properties.go b/lzma/properties.go
index 23418e2..f229fc9 100644
--- a/lzma/properties.go
+++ b/lzma/properties.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/rangecodec.go b/lzma/rangecodec.go
index 6361c5e..57f1ab9 100644
--- a/lzma/rangecodec.go
+++ b/lzma/rangecodec.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -131,32 +131,6 @@ type rangeDecoder struct {
 	code   uint32
 }
 
-// init initializes the range decoder, by reading from the byte reader.
-func (d *rangeDecoder) init() error {
-	d.nrange = 0xffffffff
-	d.code = 0
-
-	b, err := d.br.ReadByte()
-	if err != nil {
-		return err
-	}
-	if b != 0 {
-		return errors.New("newRangeDecoder: first byte not zero")
-	}
-
-	for i := 0; i < 4; i++ {
-		if err = d.updateCode(); err != nil {
-			return err
-		}
-	}
-
-	if d.code >= d.nrange {
-		return errors.New("newRangeDecoder: d.code >= d.nrange")
-	}
-
-	return nil
-}
-
 // newRangeDecoder initializes a range decoder. It reads five bytes from the
 // reader and therefore may return an error.
 func newRangeDecoder(br io.ByteReader) (d *rangeDecoder, err error) {
diff --git a/lzma/reader.go b/lzma/reader.go
index 2ef3dca..2ed13c8 100644
--- a/lzma/reader.go
+++ b/lzma/reader.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/reader2.go b/lzma/reader2.go
index a55cfaa..de3da37 100644
--- a/lzma/reader2.go
+++ b/lzma/reader2.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -48,7 +48,6 @@ type Reader2 struct {
 	chunkReader io.Reader
 
 	cstate chunkState
-	ctype  chunkType
 }
 
 // NewReader2 creates a reader for an LZMA2 chunk sequence.
diff --git a/lzma/reader_test.go b/lzma/reader_test.go
index 1fd418e..12b7ddd 100644
--- a/lzma/reader_test.go
+++ b/lzma/reader_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/state.go b/lzma/state.go
index 5023510..09d62f7 100644
--- a/lzma/state.go
+++ b/lzma/state.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -53,12 +53,6 @@ func (s *state) Reset() {
 	s.distCodec.init()
 }
 
-// initState initializes the state.
-func initState(s *state, p Properties) {
-	*s = state{Properties: p}
-	s.Reset()
-}
-
 // newState creates a new state from the give Properties.
 func newState(p Properties) *state {
 	s := &state{Properties: p}
diff --git a/lzma/treecodecs.go b/lzma/treecodecs.go
index 504b3d7..6e927e9 100644
--- a/lzma/treecodecs.go
+++ b/lzma/treecodecs.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/writer.go b/lzma/writer.go
index efe34fb..d0d220f 100644
--- a/lzma/writer.go
+++ b/lzma/writer.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/writer2.go b/lzma/writer2.go
index 7c1afe1..dfaaec9 100644
--- a/lzma/writer2.go
+++ b/lzma/writer2.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/writer2_test.go b/lzma/writer2_test.go
index 67f0d4e..b2d16f4 100644
--- a/lzma/writer2_test.go
+++ b/lzma/writer2_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzma/writer_test.go b/lzma/writer_test.go
index 4d5083b..005bfc9 100644
--- a/lzma/writer_test.go
+++ b/lzma/writer_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/lzmafilter.go b/lzmafilter.go
index 69cf5f7..4f1bb33 100644
--- a/lzmafilter.go
+++ b/lzmafilter.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/none-check.go b/none-check.go
new file mode 100644
index 0000000..9524013
--- /dev/null
+++ b/none-check.go
@@ -0,0 +1,23 @@
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xz
+
+import "hash"
+
+type noneHash struct{}
+
+func (h noneHash) Write(p []byte) (n int, err error) { return len(p), nil }
+
+func (h noneHash) Sum(b []byte) []byte { return b }
+
+func (h noneHash) Reset() {}
+
+func (h noneHash) Size() int { return 0 }
+
+func (h noneHash) BlockSize() int { return 0 }
+
+func newNoneHash() hash.Hash {
+	return &noneHash{}
+}
diff --git a/none-check_test.go b/none-check_test.go
new file mode 100644
index 0000000..619fc30
--- /dev/null
+++ b/none-check_test.go
@@ -0,0 +1,22 @@
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xz
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestNoneHash(t *testing.T) {
+	h := newNoneHash()
+
+	p := []byte("foo")
+	q := h.Sum(p)
+
+	if !bytes.Equal(q, p) {
+		t.Fatalf("h.Sum: got %q; want %q", q, p)
+	}
+
+}
diff --git a/reader.go b/reader.go
index 0634c6b..7f974ff 100644
--- a/reader.go
+++ b/reader.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -26,13 +26,6 @@ type ReaderConfig struct {
 	SingleStream bool
 }
 
-// fill replaces all zero values with their default values.
-func (c *ReaderConfig) fill() {
-	if c.DictCap == 0 {
-		c.DictCap = 8 * 1024 * 1024
-	}
-}
-
 // Verify checks the reader parameters for Validity. Zero values will be
 // replaced by default values.
 func (c *ReaderConfig) Verify() error {
@@ -165,22 +158,16 @@ func (c ReaderConfig) newStreamReader(xz io.Reader) (r *streamReader, err error)
 	return r, nil
 }
 
-// errIndex indicates an error with the xz file index.
-var errIndex = errors.New("xz: error in xz file index")
-
 // readTail reads the index body and the xz footer.
 func (r *streamReader) readTail() error {
-	index, n, err := readIndexBody(r.xz)
+	index, n, err := readIndexBody(r.xz, len(r.index))
 	if err != nil {
 		if err == io.EOF {
 			err = io.ErrUnexpectedEOF
 		}
 		return err
 	}
-	if len(index) != len(r.index) {
-		return fmt.Errorf("xz: index length is %d; want %d",
-			len(index), len(r.index))
-	}
+
 	for i, rec := range r.index {
 		if rec != index[i] {
 			return fmt.Errorf("xz: record %d is %v; want %v",
@@ -265,7 +252,6 @@ type blockReader struct {
 	n         int64
 	hash      hash.Hash
 	r         io.Reader
-	err       error
 }
 
 // newBlockReader creates a new block reader.
@@ -283,7 +269,11 @@ func (c *ReaderConfig) newBlockReader(xz io.Reader, h *blockHeader,
 	if err != nil {
 		return nil, err
 	}
-	br.r = io.TeeReader(fr, br.hash)
+	if br.hash.Size() != 0 {
+		br.r = io.TeeReader(fr, br.hash)
+	} else {
+		br.r = fr
+	}
 
 	return br, nil
 }
@@ -311,10 +301,6 @@ func (br *blockReader) record() record {
 	return record{br.unpaddedSize(), br.uncompressedSize()}
 }
 
-// errBlockSize indicates that the size of the block in the block header
-// is wrong.
-var errBlockSize = errors.New("xz: wrong uncompressed size for block")
-
 // Read reads data from the block.
 func (br *blockReader) Read(p []byte) (n int, err error) {
 	n, err = br.r.Read(p)
diff --git a/reader_test.go b/reader_test.go
index efc9f7b..a14f229 100644
--- a/reader_test.go
+++ b/reader_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -55,7 +55,7 @@ func TestReaderSingleStream(t *testing.T) {
 	}
 }
 
-func TestReaaderMultipleStreams(t *testing.T) {
+func TestReaderMultipleStreams(t *testing.T) {
 	data, err := ioutil.ReadFile("fox.xz")
 	if err != nil {
 		t.Fatalf("ReadFile error %s", err)
@@ -79,3 +79,19 @@ func TestReaaderMultipleStreams(t *testing.T) {
 		t.Fatalf("io.Copy error %s", err)
 	}
 }
+
+func TestCheckNone(t *testing.T) {
+	const file = "fox-check-none.xz"
+	xz, err := os.Open(file)
+	if err != nil {
+		t.Fatalf("os.Open(%q) error %s", file, err)
+	}
+	r, err := NewReader(xz)
+	if err != nil {
+		t.Fatalf("NewReader error %s", err)
+	}
+	var buf bytes.Buffer
+	if _, err = io.Copy(&buf, r); err != nil {
+		t.Fatalf("io.Copy error %s", err)
+	}
+}
diff --git a/writer.go b/writer.go
index c126f70..6b3a666 100644
--- a/writer.go
+++ b/writer.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -6,6 +6,7 @@ package xz
 
 import (
 	"errors"
+	"fmt"
 	"hash"
 	"io"
 
@@ -18,8 +19,10 @@ type WriterConfig struct {
 	DictCap    int
 	BufSize    int
 	BlockSize  int64
-	// checksum method: CRC32, CRC64 or SHA256
+	// checksum method: CRC32, CRC64 or SHA256 (default: CRC64)
 	CheckSum byte
+	// Forces NoChecksum (default: false)
+	NoCheckSum bool
 	// match algorithm
 	Matcher lzma.MatchAlgorithm
 }
@@ -41,6 +44,9 @@ func (c *WriterConfig) fill() {
 	if c.CheckSum == 0 {
 		c.CheckSum = CRC64
 	}
+	if c.NoCheckSum {
+		c.CheckSum = None
+	}
 }
 
 // Verify checks the configuration for errors. Zero values will be
@@ -185,6 +191,9 @@ func (c WriterConfig) NewWriter(xz io.Writer) (w *Writer, err error) {
 		return nil, err
 	}
 	data, err := w.h.MarshalBinary()
+	if err != nil {
+		return nil, fmt.Errorf("w.h.MarshalBinary(): error %w", err)
+	}
 	if _, err = xz.Write(data); err != nil {
 		return nil, err
 	}
@@ -284,7 +293,11 @@ func (c *WriterConfig) newBlockWriter(xz io.Writer, hash hash.Hash) (bw *blockWr
 	if err != nil {
 		return nil, err
 	}
-	bw.mw = io.MultiWriter(bw.w, bw.hash)
+	if bw.hash.Size() != 0 {
+		bw.mw = io.MultiWriter(bw.w, bw.hash)
+	} else {
+		bw.mw = bw.w
+	}
 	return bw, nil
 }
 
diff --git a/writer_test.go b/writer_test.go
index b45e85c..f167b6c 100644
--- a/writer_test.go
+++ b/writer_test.go
@@ -1,4 +1,4 @@
-// Copyright 2014-2017 Ulrich Kunitz. All rights reserved.
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -136,3 +136,42 @@ func TestWriter2(t *testing.T) {
 		t.Fatal("decompressed data differs from original")
 	}
 }
+
+func TestWriterNoneCheck(t *testing.T) {
+	const txtlen = 1023
+	var buf bytes.Buffer
+	io.CopyN(&buf, randtxt.NewReader(rand.NewSource(41)), txtlen)
+	txt := buf.String()
+
+	buf.Reset()
+	w, err := WriterConfig{NoCheckSum: true}.NewWriter(&buf)
+	if err != nil {
+		t.Fatalf("NewWriter error %s", err)
+	}
+	n, err := io.WriteString(w, txt)
+	if err != nil {
+		t.Fatalf("WriteString error %s", err)
+	}
+	if n != len(txt) {
+		t.Fatalf("WriteString wrote %d bytes; want %d", n, len(txt))
+	}
+	if err = w.Close(); err != nil {
+		t.Fatalf("Close error %s", err)
+	}
+	t.Logf("buf.Len() %d", buf.Len())
+	r, err := NewReader(&buf)
+	if err != nil {
+		t.Fatalf("NewReader error %s", err)
+	}
+	var out bytes.Buffer
+	k, err := io.Copy(&out, r)
+	if err != nil {
+		t.Fatalf("Decompressing copy error %s after %d bytes", err, n)
+	}
+	if k != txtlen {
+		t.Fatalf("Decompression data length %d; want %d", k, txtlen)
+	}
+	if txt != out.String() {
+		t.Fatal("decompressed data differs from original")
+	}
+}
diff --git a/xz_test.go b/xz_test.go
new file mode 100644
index 0000000..ac0b476
--- /dev/null
+++ b/xz_test.go
@@ -0,0 +1,29 @@
+// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xz_test
+
+import (
+	"bytes"
+	"io/ioutil"
+	"testing"
+
+	"github.com/ulikunitz/xz"
+)
+
+func TestPanic(t *testing.T) {
+	data := []byte([]uint8{253, 55, 122, 88, 90, 0, 0, 0, 255, 18, 217, 65, 0, 189, 191, 239, 189, 191, 239, 48})
+	t.Logf("%q", string(data))
+	t.Logf("0x%02x", data)
+	r, err := xz.NewReader(bytes.NewReader(data))
+	if err != nil {
+		t.Logf("xz.NewReader error %s", err)
+		return
+	}
+	_, err = ioutil.ReadAll(r)
+	if err != nil {
+		t.Logf("ioutil.ReadAll(r) error %s", err)
+		return
+	}
+}