Merge pull request #26969 from mheon/backports_561

Backports for v5.6.1
This commit is contained in:
openshift-merge-bot[bot]
2025-09-03 11:21:49 +00:00
committed by GitHub
18 changed files with 243 additions and 93 deletions

View File

@ -1,5 +1,12 @@
# Release Notes
## 5.6.1
### Bugfixes
- Fixed a bug where network creation and removal events were displayed incorrectly when the `journald` events driver was in use.
- Fixed a bug where the `--security-opt seccomp=unconfined` option was broken on Windows ([#26855](https://github.com/containers/podman/issues/26855)).
- Fixed a bug where containers created with a name longer than 64 characters, no explicit hostname, the the `container_name_as_hostname` option in `containers.conf` set to `true` would fail to start.
- Fixed a bug where Podman would fail to start containers when runc 1.3.0 or later was used as the OCI runtime ([#26938](https://github.com/containers/podman/issues/26938)).
## 5.6.0
### Features
- A new set of commands for managing Quadlets has been added as `podman quadlet install` (install a new Quadlet for the current user), `podman quadlet list` (list installed Quadlets), `podman quadlet print` (print the contents of a Quadlet file), and `podman quadlet rm` (remove a Quadlet). These commands are presently not available with the remote Podman client - we expect support for this to arrive in a future release.

2
go.mod
View File

@ -170,7 +170,7 @@ require (
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.9.0 // indirect
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/ulikunitz/xz v0.5.15 // indirect
github.com/vbatts/tar-split v0.12.1 // indirect
github.com/vishvananda/netns v0.0.5 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect

4
go.sum
View File

@ -434,8 +434,8 @@ github.com/u-root/u-root v0.12.1-0.20240114161452-ab3534910ced h1:G0F7Hmwph1Ojoz
github.com/u-root/u-root v0.12.1-0.20240114161452-ab3534910ced/go.mod h1:jtkuv6BVn5jo/WAHgQ1k9XfzHEe1hZmq9yDUvbgL+Iw=
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
github.com/vbauerster/mpb/v8 v8.10.2 h1:2uBykSHAYHekE11YvJhKxYmLATKHAGorZwFlyNw4hHM=

View File

@ -741,14 +741,14 @@ func (c *Container) hostname(network bool) string {
// containers.conf, use a sanitized version of the container's name
// as the hostname. Since the container name must already match
// the set '[a-zA-Z0-9][a-zA-Z0-9_.-]*', we can just remove any
// underscores and limit it to 253 characters to make it a valid
// underscores and limit it to 64 characters to make it a valid
// hostname.
if c.runtime.config.Containers.ContainerNameAsHostName {
sanitizedHostname := strings.ReplaceAll(c.Name(), "_", "")
if len(sanitizedHostname) <= 253 {
if len(sanitizedHostname) <= 64 {
return sanitizedHostname
}
return sanitizedHostname[:253]
return sanitizedHostname[:64]
}
// Otherwise use the container's short ID as the hostname.

View File

@ -420,6 +420,8 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc
// Podman decided for --no-dereference as many
// bin-utils tools (e..g, touch, chown, cp) do.
options = append(options, "copy-symlink")
case "copy", "nocopy":
// no real OCI runtime bind mount options, these should already be handled by the named volume mount above
default:
options = append(options, o)
}

View File

@ -504,6 +504,15 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
_, err := r.state.Volume(vol.Name)
if err == nil {
// The volume exists, we're good
// Make sure to drop all volume-opt options as they only apply to
// the volume create which we don't do again.
var volOpts []string
for _, opts := range vol.Options {
if !strings.HasPrefix(opts, "volume-opt") {
volOpts = append(volOpts, opts)
}
}
vol.Options = volOpts
continue
} else if !errors.Is(err, define.ErrNoSuchVolume) {
return nil, fmt.Errorf("retrieving named volume %s for new container: %w", vol.Name, err)
@ -530,6 +539,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
if len(vol.Options) > 0 {
isDriverOpts := false
driverOpts := make(map[string]string)
var volOpts []string
for _, opts := range vol.Options {
if strings.HasPrefix(opts, "volume-opt") {
isDriverOpts = true
@ -538,8 +548,11 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
return nil, err
}
driverOpts[driverOptKey] = driverOptValue
} else {
volOpts = append(volOpts, opts)
}
}
vol.Options = volOpts
if isDriverOpts {
parsedOptions := []VolumeCreateOption{WithVolumeOptions(driverOpts)}
volOptions = append(volOptions, parsedOptions...)

View File

@ -788,7 +788,7 @@ var _ = Describe("Verify podman containers.conf usage", func() {
})
startContainer := func(params ...string) string {
args := []string{"create"}
args := []string{"run", "-d"}
for _, param := range params {
if param == "--name" {
args = append(args, "--replace")
@ -888,7 +888,7 @@ var _ = Describe("Verify podman containers.conf usage", func() {
name = getContainerConfig(containerID, "{{ .Name }}")
// Double check that name actually got set correctly
Expect(name).To(Equal(longHostname))
// Hostname should be the container name truncated to 253 characters
Expect(hostname).To(Equal(name[:253]))
// Hostname should be the container name truncated to 64 characters
Expect(hostname).To(Equal(name[:64]))
})
})

View File

@ -3,17 +3,20 @@
package integration
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"os/user"
"path/filepath"
"strconv"
"strings"
. "github.com/containers/podman/v5/test/utils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
"github.com/opencontainers/runtime-spec/specs-go"
)
// in-container mount point: using a path that is definitely not present
@ -447,9 +450,27 @@ var _ = Describe("Podman run with volumes", func() {
Expect(separateVolumeSession).Should(ExitCleanly())
Expect(separateVolumeSession.OutputToString()).To(Equal(baselineOutput))
copySession := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol3:/etc/apk:copy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch"})
copySession.WaitWithDefaultTimeout()
Expect(copySession).Should(ExitCleanly())
podmanTest.PodmanExitCleanly("run", "--name", "testctr", "-v", "testvol3:/etc/apk:copy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch")
inspect := podmanTest.PodmanExitCleanly("container", "inspect", "testctr", "--format", "{{.OCIConfigPath}}")
// Make extra check that the OCI config does not contain the copy opt, runc 1.3.0 fails on that while crun does not.
// We only test crun upstream so make sure the spec is sane: https://github.com/containers/podman/issues/26938
f, err := os.Open(inspect.OutputToString())
Expect(err).ToNot(HaveOccurred())
defer f.Close()
var spec specs.Spec
err = json.NewDecoder(f).Decode(&spec)
Expect(err).ToNot(HaveOccurred())
found := false
for _, m := range spec.Mounts {
if m.Destination == "/etc/apk" {
found = true
Expect(m.Options).To(Equal([]string{"rprivate", "nosuid", "nodev", "rbind"}))
}
}
Expect(found).To(BeTrue(), "OCI spec contains /etc/apk mount")
noCopySession := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol4:/etc/apk:nocopy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch"})
noCopySession.WaitWithDefaultTimeout()
@ -859,14 +880,17 @@ VOLUME /test/`, ALPINE)
It("podman run with --mount and named volume with driver-opts", func() {
// anonymous volume mount with driver opts
vol := "type=volume,source=test_vol,dst=/test,volume-opt=type=tmpfs,volume-opt=device=tmpfs,volume-opt=o=nodev"
session := podmanTest.Podman([]string{"run", "--rm", "--mount", vol, ALPINE, "echo", "hello"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
// Loop twice to cover both the initial code path that creates the volume and the ones which reuses it.
for i := range 2 {
name := "testctr" + strconv.Itoa(i)
podmanTest.PodmanExitCleanly("run", "--name", name, "--mount", vol, ALPINE, "echo", "hello")
inspectVol := podmanTest.Podman([]string{"volume", "inspect", "test_vol"})
inspectVol.WaitWithDefaultTimeout()
Expect(inspectVol).Should(ExitCleanly())
Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev"))
inspectVol := podmanTest.PodmanExitCleanly("volume", "inspect", "test_vol")
Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev"))
inspect := podmanTest.PodmanExitCleanly("container", "inspect", name, "--format", "{{range .Mounts}}{{.Options}}{{end}}")
Expect(inspect.OutputToString()).To(ContainSubstring("[nosuid nodev rbind]"))
}
})
It("volume permissions after run", func() {

View File

@ -338,7 +338,7 @@ EOF
# send a random string to the container. This will cause the container
# to output the string to its logs, then exit.
teststring=$(random_string 30)
echo "$teststring" | nc 127.0.0.1 $port_out
echo "$teststring" > /dev/tcp/127.0.0.1/$port_out
# Confirm that the container log output is the string we sent it.
run_podman wait $cid

View File

@ -1188,8 +1188,8 @@ spec:
EOF
# Bind the port to force a an error when starting the pod
timeout --foreground -v --kill=10 10 ncat -l 127.0.0.1 $port &
nc_pid=$!
timeout --foreground -v --kill=10 10 socat TCP-LISTEN:$port,bind=127.0.0.1,fork - &
socat_pid=$!
# Create the Quadlet file
local quadlet_file=$PODMAN_TMPDIR/start_err_$(safename).kube
@ -1214,7 +1214,7 @@ EOF
run -0 journalctl -eu $QUADLET_SERVICE_NAME
assert "$output" =~ "$port: bind: address already in use" "journal contains the real podman start error"
kill "$nc_pid"
kill "$socat_pid"
}
# https://github.com/containers/podman/issues/25786

View File

@ -153,7 +153,7 @@ load helpers.network
# emit random string, and check it
teststring=$(random_string 30)
echo "$teststring" | nc 127.0.0.1 $myport
echo "$teststring" > /dev/tcp/127.0.0.1/$myport
run_podman logs $cid
# Sigh. We can't check line-by-line, because 'nc' output order is
@ -296,7 +296,7 @@ load helpers.network
# emit random string, and check it
teststring=$(random_string 30)
echo "$teststring" | nc 127.0.0.1 $myport
echo "$teststring" > /dev/tcp/127.0.0.1/$myport
run_podman logs $cid
# Sigh. We can't check line-by-line, because 'nc' output order is
@ -806,26 +806,26 @@ nameserver 8.8.8.8" "nameserver order is correct"
cid="$output"
# make sure binding the same port fails
run timeout 5 ncat -l 127.0.0.1 $port
assert "$status" -eq 2 "ncat unexpected exit code"
assert "$output" =~ "127.0.0.1:$port: Address already in use" "ncat error message"
run timeout 5 socat TCP-LISTEN:$port,bind=127.0.0.1,fork -
assert "$status" -eq 1 "socat unexpected exit code"
assert "$output" =~ ".* 127.0.0.1:$port.* Address already in use" "socat error message"
for port in $(seq $port $end_port); do
run_podman exec -d $cid nc -l -p $port -e /bin/cat
# we have to rety ncat as it can flake as we exec in the background so nc -l
# we have to retry socat as it can flake as we exec in the background so nc -l
# might not have bound the port yet, retry seems simpler than checking if the
# port is bound in the container, https://github.com/containers/podman/issues/21561.
retries=5
while [[ $retries -gt 0 ]]; do
run ncat 127.0.0.1 $port <<<$random
run socat - TCP:127.0.0.1:$port <<<$random
if [[ $status -eq 0 ]]; then
break
fi
sleep 0.5
retries=$((retries -1))
done
is "$output" "$random" "ncat got data back (netmode=$netmode port=$port)"
is "$output" "$random" "socat got data back (netmode=$netmode port=$port)"
done
run_podman rm -f -t0 $cid

View File

@ -86,7 +86,6 @@ Requirements
- bats
- jq
- skopeo
- nmap-ncat
- httpd-tools
- openssl
- socat

View File

@ -423,7 +423,7 @@ function wait_for_port() {
function tcp_port_probe() {
local address="${2:-0.0.0.0}"
: | nc "${address}" "${1}"
(exec echo -n >/dev/tcp/"$address/$1") >/dev/null 2>&1
}
### Pasta Helpers ##############################################################

View File

@ -1,9 +1,5 @@
# 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.
@ -86,6 +82,19 @@
## Log
## 2025-08-28
Release v0.5.14 addresses the security vulnerability CVE-2025-58058. If you put
bytes in from of a LZMA stream, the header might not be read correctly and
memory for the dictionary buffer allocated. I have implemented mitigations for
the problem.
### 2025-08-20
Release v0.5.13 addressed issue #61 regarding handling of multiple WriteClosers
together. So I added a new package xio with a WriteCloserStack to address the
issue.
### 2024-04-03
Release v0.5.12 updates README.md and SECURITY.md to address the supply chain

View File

@ -60,36 +60,36 @@ const noHeaderSize uint64 = 1<<64 - 1
// HeaderLen provides the length of the LZMA file header.
const HeaderLen = 13
// header represents the header of an LZMA file.
type header struct {
properties Properties
dictCap int
// uncompressed size; negative value if no size is given
size int64
// Header represents the Header of an LZMA file.
type Header struct {
Properties Properties
DictSize uint32
// uncompressed Size; negative value if no Size is given
Size int64
}
// marshalBinary marshals the header.
func (h *header) marshalBinary() (data []byte, err error) {
if err = h.properties.verify(); err != nil {
func (h *Header) marshalBinary() (data []byte, err error) {
if err = h.Properties.verify(); err != nil {
return nil, err
}
if !(0 <= h.dictCap && int64(h.dictCap) <= MaxDictCap) {
if !(h.DictSize <= MaxDictCap) {
return nil, fmt.Errorf("lzma: DictCap %d out of range",
h.dictCap)
h.DictSize)
}
data = make([]byte, 13)
// property byte
data[0] = h.properties.Code()
data[0] = h.Properties.Code()
// dictionary capacity
putUint32LE(data[1:5], uint32(h.dictCap))
putUint32LE(data[1:5], uint32(h.DictSize))
// uncompressed size
var s uint64
if h.size > 0 {
s = uint64(h.size)
if h.Size > 0 {
s = uint64(h.Size)
} else {
s = noHeaderSize
}
@ -99,20 +99,20 @@ func (h *header) marshalBinary() (data []byte, err error) {
}
// unmarshalBinary unmarshals the header.
func (h *header) unmarshalBinary(data []byte) error {
func (h *Header) unmarshalBinary(data []byte) error {
if len(data) != HeaderLen {
return errors.New("lzma.unmarshalBinary: data has wrong length")
}
// properties
var err error
if h.properties, err = PropertiesForCode(data[0]); err != nil {
if h.Properties, err = PropertiesForCode(data[0]); err != nil {
return err
}
// dictionary capacity
h.dictCap = int(uint32LE(data[1:]))
if h.dictCap < 0 {
h.DictSize = uint32LE(data[1:])
if int(h.DictSize) < 0 {
return errors.New(
"LZMA header: dictionary capacity exceeds maximum " +
"integer")
@ -121,10 +121,10 @@ func (h *header) unmarshalBinary(data []byte) error {
// uncompressed size
s := uint64LE(data[5:])
if s == noHeaderSize {
h.size = -1
h.Size = -1
} else {
h.size = int64(s)
if h.size < 0 {
h.Size = int64(s)
if h.Size < 0 {
return errors.New(
"LZMA header: uncompressed size " +
"out of int64 range")
@ -134,9 +134,9 @@ func (h *header) unmarshalBinary(data []byte) error {
return nil
}
// validDictCap checks whether the dictionary capacity is correct. This
// validDictSize checks whether the dictionary capacity is correct. This
// is used to weed out wrong file headers.
func validDictCap(dictcap int) bool {
func validDictSize(dictcap int) bool {
if int64(dictcap) == MaxDictCap {
return true
}
@ -155,13 +155,16 @@ func validDictCap(dictcap int) bool {
// dictionary sizes of 2^n or 2^n+2^(n-1) with n >= 10 or 2^32-1. If
// there is an explicit size it must not exceed 256 GiB. The length of
// the data argument must be HeaderLen.
//
// This function should be disregarded because there is no guarantee that LZMA
// files follow the constraints.
func ValidHeader(data []byte) bool {
var h header
var h Header
if err := h.unmarshalBinary(data); err != nil {
return false
}
if !validDictCap(h.dictCap) {
if !validDictSize(int(h.DictSize)) {
return false
}
return h.size < 0 || h.size <= 1<<38
return h.Size < 0 || h.Size <= 1<<38
}

View File

@ -6,25 +6,32 @@
// Reader and Writer support the classic LZMA format. Reader2 and
// Writer2 support the decoding and encoding of LZMA2 streams.
//
// The package is written completely in Go and doesn't rely on any external
// The package is written completely in Go and does not rely on any external
// library.
package lzma
import (
"errors"
"fmt"
"io"
)
// ReaderConfig stores the parameters for the reader of the classic LZMA
// format.
type ReaderConfig struct {
// Since v0.5.14 this parameter sets an upper limit for a .lzma file's
// dictionary size. This helps to mitigate problems with mangled
// headers.
DictCap int
}
// fill converts the zero values of the configuration to the default values.
func (c *ReaderConfig) fill() {
if c.DictCap == 0 {
c.DictCap = 8 * 1024 * 1024
// set an upper limit of 2 GiB-1 for dictionary capacity
// to address the zero prefix security issue.
c.DictCap = (1 << 31) - 1
// original: c.DictCap = 8 * 1024 * 1024
}
}
@ -39,10 +46,33 @@ func (c *ReaderConfig) Verify() error {
}
// Reader provides a reader for LZMA files or streams.
//
// # Security concerns
//
// Note that LZMA format doesn't support a magic marker in the header. So
// [NewReader] cannot determine whether it reads the actual header. For instance
// the LZMA stream might have a zero byte in front of the reader, leading to
// larger dictionary sizes and file sizes. The code will detect later that there
// are problems with the stream, but the dictionary has already been allocated
// and this might consume a lot of memory.
//
// Version 0.5.14 introduces built-in mitigations:
//
// - The [ReaderConfig] DictCap field is now interpreted as a limit for the
// dictionary size.
// - The default is 2 Gigabytes minus 1 byte (2^31-1 bytes).
// - Users can check with the [Reader.Header] method what the actual values are in
// their LZMA files and set a smaller limit using [ReaderConfig].
// - The dictionary size doesn't exceed the larger of the file size and
// the minimum dictionary size. This is another measure to prevent huge
// memory allocations for the dictionary.
// - The code supports stream sizes only up to a pebibyte (1024^5).
type Reader struct {
lzma io.Reader
h header
d *decoder
lzma io.Reader
header Header
// headerOrig stores the original header read from the stream.
headerOrig Header
d *decoder
}
// NewReader creates a new reader for an LZMA stream using the classic
@ -51,8 +81,37 @@ func NewReader(lzma io.Reader) (r *Reader, err error) {
return ReaderConfig{}.NewReader(lzma)
}
// ErrDictSize reports about an error of the dictionary size.
type ErrDictSize struct {
ConfigDictCap int
HeaderDictSize uint32
Message string
}
// Error returns the error message.
func (e *ErrDictSize) Error() string {
return e.Message
}
func newErrDictSize(messageformat string,
configDictCap int, headerDictSize uint32,
args ...interface{}) *ErrDictSize {
newArgs := make([]interface{}, len(args)+2)
newArgs[0] = configDictCap
newArgs[1] = headerDictSize
copy(newArgs[2:], args)
return &ErrDictSize{
ConfigDictCap: configDictCap,
HeaderDictSize: headerDictSize,
Message: fmt.Sprintf(messageformat, newArgs...),
}
}
// We support only files not larger than 1 << 50 bytes (a pebibyte, 1024^5).
const maxStreamSize = 1 << 50
// NewReader creates a new reader for an LZMA stream in the classic
// format. The function reads and verifies the the header of the LZMA
// format. The function reads and verifies the header of the LZMA
// stream.
func (c ReaderConfig) NewReader(lzma io.Reader) (r *Reader, err error) {
if err = c.Verify(); err != nil {
@ -66,29 +125,63 @@ func (c ReaderConfig) NewReader(lzma io.Reader) (r *Reader, err error) {
return nil, err
}
r = &Reader{lzma: lzma}
if err = r.h.unmarshalBinary(data); err != nil {
if err = r.header.unmarshalBinary(data); err != nil {
return nil, err
}
if r.h.dictCap < MinDictCap {
r.h.dictCap = MinDictCap
r.headerOrig = r.header
dictSize := int64(r.header.DictSize)
if int64(c.DictCap) < dictSize {
return nil, newErrDictSize(
"lzma: header dictionary size %[2]d exceeds configured dictionary capacity %[1]d",
c.DictCap, uint32(dictSize),
)
}
dictCap := r.h.dictCap
if c.DictCap > dictCap {
dictCap = c.DictCap
if dictSize < MinDictCap {
dictSize = MinDictCap
}
// original code: disabled this because there is no point in increasing
// the dictionary above what is stated in the file.
/*
if int64(c.DictCap) > int64(dictSize) {
dictSize = int64(c.DictCap)
}
*/
size := r.header.Size
if size >= 0 && size < dictSize {
dictSize = size
}
// Protect against modified or malicious headers.
if size > maxStreamSize {
return nil, fmt.Errorf(
"lzma: stream size %d exceeds a pebibyte (1024^5)",
size)
}
if dictSize < MinDictCap {
dictSize = MinDictCap
}
state := newState(r.h.properties)
dict, err := newDecoderDict(dictCap)
r.header.DictSize = uint32(dictSize)
state := newState(r.header.Properties)
dict, err := newDecoderDict(int(dictSize))
if err != nil {
return nil, err
}
r.d, err = newDecoder(ByteReader(lzma), state, dict, r.h.size)
r.d, err = newDecoder(ByteReader(lzma), state, dict, r.header.Size)
if err != nil {
return nil, err
}
return r, nil
}
// Header returns the header as read from the LZMA stream. It is intended to
// allow the user to understand what parameters are typically provided in the
// headers of the LZMA files and set the DictCap field in [ReaderConfig]
// accordingly.
func (r *Reader) Header() (h Header, ok bool) {
return r.headerOrig, r.d != nil
}
// EOSMarker indicates that an EOS marker has been encountered.
func (r *Reader) EOSMarker() bool {
return r.d.eosMarker

View File

@ -96,21 +96,21 @@ func (c *WriterConfig) Verify() error {
}
// header returns the header structure for this configuration.
func (c *WriterConfig) header() header {
h := header{
properties: *c.Properties,
dictCap: c.DictCap,
size: -1,
func (c *WriterConfig) header() Header {
h := Header{
Properties: *c.Properties,
DictSize: uint32(c.DictCap),
Size: -1,
}
if c.SizeInHeader {
h.size = c.Size
h.Size = c.Size
}
return h
}
// Writer writes an LZMA stream in the classic format.
type Writer struct {
h header
h Header
bw io.ByteWriter
buf *bufio.Writer
e *encoder
@ -130,12 +130,12 @@ func (c WriterConfig) NewWriter(lzma io.Writer) (w *Writer, err error) {
w.buf = bufio.NewWriter(lzma)
w.bw = w.buf
}
state := newState(w.h.properties)
m, err := c.Matcher.new(w.h.dictCap)
state := newState(w.h.Properties)
m, err := c.Matcher.new(int(w.h.DictSize))
if err != nil {
return nil, err
}
dict, err := newEncoderDict(w.h.dictCap, c.BufSize, m)
dict, err := newEncoderDict(int(w.h.DictSize), c.BufSize, m)
if err != nil {
return nil, err
}
@ -171,8 +171,8 @@ func (w *Writer) writeHeader() error {
// Write puts data into the Writer.
func (w *Writer) Write(p []byte) (n int, err error) {
if w.h.size >= 0 {
m := w.h.size
if w.h.Size >= 0 {
m := w.h.Size
m -= w.e.Compressed() + int64(w.e.dict.Buffered())
if m < 0 {
m = 0
@ -192,9 +192,9 @@ func (w *Writer) Write(p []byte) (n int, err error) {
// Close closes the writer stream. It ensures that all data from the
// buffer will be compressed and the LZMA stream will be finished.
func (w *Writer) Close() error {
if w.h.size >= 0 {
if w.h.Size >= 0 {
n := w.e.Compressed() + int64(w.e.dict.Buffered())
if n != w.h.size {
if n != w.h.Size {
return errSize
}
}

2
vendor/modules.txt vendored
View File

@ -899,7 +899,7 @@ github.com/tklauser/numcpus
# github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701
## explicit; go 1.21
github.com/u-root/uio/ulog
# github.com/ulikunitz/xz v0.5.12
# github.com/ulikunitz/xz v0.5.15
## explicit; go 1.12
github.com/ulikunitz/xz
github.com/ulikunitz/xz/internal/hash