Skip to content

Commit 7150e60

Browse files
committed
fix: Add ARM64 filter support
1 parent 0af225b commit 7150e60

File tree

5 files changed

+96
-1
lines changed

5 files changed

+96
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Current status:
2121
* Handles archives split into multiple volumes, (`7za a -v100m test.7z ...`).
2222
* Handles self-extracting archives, (`7za a -sfx archive.exe ...`).
2323
* Validates CRC values as it parses the file.
24-
* Supports ARM, BCJ, BCJ2, Brotli, Bzip2, Copy, Deflate, Delta, LZ4, LZMA, LZMA2, PPC, SPARC and Zstandard methods.
24+
* Supports ARM, ARM64, BCJ, BCJ2, Brotli, Bzip2, Copy, Deflate, Delta, LZ4, LZMA, LZMA2, PPC, SPARC and Zstandard methods.
2525
* Implements the `fs.FS` interface so you can treat an opened 7-zip archive like a filesystem.
2626

2727
More examples of 7-zip archives are needed to test all of the different combinations/algorithms possible.

internal/bra/arm64.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package bra
2+
3+
import (
4+
"encoding/binary"
5+
"io"
6+
)
7+
8+
const arm64Alignment = 4
9+
10+
type arm64 struct {
11+
ip uint32
12+
}
13+
14+
func (c *arm64) Size() int { return arm64Alignment }
15+
16+
//nolint:funlen
17+
func (c *arm64) Convert(b []byte, encoding bool) int {
18+
if len(b) < c.Size() {
19+
return 0
20+
}
21+
22+
var i int
23+
24+
for i = 0; i < len(b) & ^(arm64Alignment-1); i += arm64Alignment {
25+
v := binary.LittleEndian.Uint32(b[i:])
26+
27+
if (v-0x94000000)&0xfc000000 == 0 {
28+
v <<= 2
29+
30+
if encoding {
31+
v += c.ip
32+
} else {
33+
v -= c.ip
34+
}
35+
36+
v >>= 2
37+
v &= 0x03ffffff
38+
v |= 0x94000000
39+
40+
binary.LittleEndian.PutUint32(b[i:], v)
41+
42+
goto next
43+
}
44+
45+
v -= 0x90000000
46+
47+
if v&0x9f000000 == 0 {
48+
const (
49+
flag = uint32(1) << (24 - 4)
50+
mask = uint32(1)<<24 - flag<<1
51+
)
52+
53+
v += flag
54+
55+
if v&mask > 0 {
56+
goto next
57+
}
58+
59+
z, ip := v&0xffffffe0|v>>26, (c.ip>>(12-3)) & ^uint32(7)
60+
61+
if encoding {
62+
z += ip
63+
} else {
64+
z -= ip
65+
}
66+
67+
v &= 0x1f
68+
v |= 0x90000000
69+
v |= z << 26
70+
v |= 0x00ffffe0 & ((z & (flag<<1 - 1)) - flag)
71+
72+
binary.LittleEndian.PutUint32(b[i:], v)
73+
}
74+
75+
next:
76+
c.ip += uint32(arm64Alignment)
77+
}
78+
79+
return i
80+
}
81+
82+
// NewARM64Reader returns a new ARM64 io.ReadCloser.
83+
func NewARM64Reader(_ []byte, _ uint64, readers []io.ReadCloser) (io.ReadCloser, error) {
84+
return newReader(readers, new(arm64))
85+
}

reader_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ func TestOpenReader(t *testing.T) {
197197
file: "COMPRESS-492.7z",
198198
err: sevenzip.ErrMissingUnpackInfo,
199199
},
200+
{
201+
name: "arm64",
202+
file: "arm64.7z",
203+
},
200204
}
201205

202206
for _, table := range tables {
@@ -657,3 +661,7 @@ func BenchmarkARM(b *testing.B) {
657661
func BenchmarkSPARC(b *testing.B) {
658662
benchmarkArchive(b, "sparc.7z", "", true)
659663
}
664+
665+
func BenchmarkARM64(b *testing.B) {
666+
benchmarkArchive(b, "arm64.7z", "", true)
667+
}

register.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ func init() {
6969
RegisterDecompressor([]byte{0x04, 0xf7, 0x11, 0x04}, Decompressor(lz4.NewReader))
7070
// AES-CBC-256 & SHA-256
7171
RegisterDecompressor([]byte{0x06, 0xf1, 0x07, 0x01}, Decompressor(aes7z.NewReader))
72+
// ARM64
73+
RegisterDecompressor([]byte{0x0a}, Decompressor(bra.NewARM64Reader))
7274
// LZMA2
7375
RegisterDecompressor([]byte{0x21}, Decompressor(lzma2.NewReader))
7476
}

testdata/arm64.7z

48.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)