Compare commits

...
Author SHA1 Message Date
catandmaemachinebroke 4be159de30 internal/rosa/package: net-tools
These are nice to have, but will not be included in the base system.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:51 -05:00
catandmaemachinebroke 566b6317a9 internal/rosa/package/nss: 3.126 to 3.126.1
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 9445e76907 internal/rosa/package/go: 1.26.5 to 1.26.6
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 79fb336160 internal/rosa/package/procps: 4.0.6 to 4.0.7
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke fbbd422e22 internal/rosa/package/harfbuzz: 14.3.0 to 14.3.1
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke dc939292b6 internal/pkg: deduplicate unwrapped input errors
This avoids repeating errors belonging to multiple instances of the same artifact in different locations in memory.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 5508702425 internal/rosa/package/qemu: disable broken tests
The copy-before-write test was failing on a Haswell machine, although it seems to work pretty reliably on the Zen 3 workstation and RK3588.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 4f885022b8 cmd/hakurei: terminate specified instance
This is theoretically susceptible to the PID race, but such an event is statistically impossible, and not exploitable in the intended use case, regardless.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 5fe7ccaa50 internal/rosa/package/qemu: use system meson
This also enables meson colour and fixes test suite invocation.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke dea9b43d0c internal/rosa/package/dbus: xdg-dbus-proxy 0.1.7 to 0.1.8
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 323c7a7f1d internal/rosa/package/qemu: 11.0.3 to 11.1.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 8b6b04c952 internal/rosa/package/python: wheel 0.47.0 to 0.48.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 97413580ed internal/pkg: in-flight error resolution
The DCE is a slow and overcomplicated solution to a simple problem. This change replaces the DCE by resolving errors in-flight.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke a2b1909b1c internal/rosa/package/python: hatchling 1.17.1 to 1.18.0
This has gained another dependency, pulling in the fourth python build system we have had to package.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 38e47847b4 internal/rosa/package/python: poetry-core tomlkit
This is the fourth python build system required to package meson. Required by tomlkit which is now required by hatchling (yet another build system).

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 73bcc97558 internal/rosa/package: replace pkg-config
This replaces pkg-config with pkgconf for most packages.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 9060fb40f3 internal/rosa/package: pkgconf
This replaces pkg-config for packages later than meson.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 2715603410 internal/rosa: improve nil-exec error reporting
This panics with a more descriptive error instead of relying on the SIGSEGV handler.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 607427ef1a internal/rosa/package/libpsl: 0.23.1 to 0.23.2
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke e89a468506 internal/rosa/package/libexpat: 2.8.2 to 2.8.3
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke cbe6814ff3 internal/rosa/package/googletest: 1.17.0 to 1.18.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 3945f847aa internal/rosa/package/firmware: 20260622 to 20260810
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 9ccb8328dd internal/rosa/package/meson: 1.11.2 to 1.12.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 9d9cf1782c internal/rosa/package/kernel: 6.18.43 to 6.18.44
Typo fix of rkisp1_ext_param_buffer_version caused world rebuild.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke d71128deee internal/rosa: improve helper bindings
This uses more intuitive names for some arguments and inverts their default value. Slices and nil-capable strings replace skip arguments.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke e9950a2291 internal/rosa/azalea: implement nil identifier
This also implements a nil-capable string type.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 2d8ba0f23b internal/rosa: optionally block packages from early stages
This helps avoid inadvertently increasing bootstrap input count.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 9e045139da internal/rosa/package/hakurei: 0.4.5 to 0.4.6
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 14b304fb3e release: 0.4.6
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 280c4fd997 cmd/dist: replace readme with license
The readme document is pretty useless for anything other than the website, so replace it with something more relevant.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
catandmaemachinebroke 8f6c04ea1b internal/rosa/package/python: setuptools 83.0.0 to 84.0.0
This has also turned into AI slop at some point, although its quality was never great to begin with. This may be a candidate to pin and ignore.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-17 08:01:50 -05:00
maemachinebroke 95a6014ec1 internal/rosa/azalea: additional test 2026-08-08 19:08:25 -05:00
maemachinebroke 9eb3ecd942 internal/rosa/azalea: refactor delimiter insertion, add test 2026-08-08 14:25:37 -05:00
maemachinebroke a81e2f251c internal/rosa/azalea: simplified delimiter insertion function 2026-08-08 11:58:30 -05:00
maemachinebroke aaabe8851c internal/rosa/azalea: add mesa test 2026-08-08 11:58:30 -05:00
maemachinebroke fec6265ac7 internal/rosa/azalea: improve delimiter insertion 2026-08-08 11:58:30 -05:00
maemachinebroke bcb92ea346 internal/rosa/azalea: implement semicolon and comma insertion 2026-08-08 11:58:30 -05:00
maemachinebroke 052ec33a04 internal/rosa/azalea: implement semicolon and comma insertion 2026-08-08 11:58:30 -05:00
94 changed files with 1369 additions and 626 deletions
+1 -1
View File
@@ -1 +1 @@
v0.4.5 v0.4.6
+6
View File
@@ -36,6 +36,11 @@ _hakurei_show() {
'files:files:__hakurei_files' 'files:files:__hakurei_files'
} }
_hakurei_kill() {
_alternative \
'instances:domains:__hakurei_instances'
}
__hakurei_files() { __hakurei_files() {
_files -g "*.(json|hakurei)" _files -g "*.(json|hakurei)"
return $? return $?
@@ -60,6 +65,7 @@ __hakurei_instances() {
"run:Load and start container from configuration file" "run:Load and start container from configuration file"
"exec:Configure and start a permissive container" "exec:Configure and start a permissive container"
"show:Show live or local instance configuration" "show:Show live or local instance configuration"
"kill:Terminate an active instance"
"ps:List active instances" "ps:List active instances"
"version:Display version information" "version:Display version information"
"license:Show full license text" "license:Show full license text"
+2 -2
View File
@@ -217,7 +217,7 @@ func main() {
mustWriteFile("comp/", nil, os.ModeDir|0755) mustWriteFile("comp/", nil, os.ModeDir|0755)
mustWriteFile("comp/_hakurei", comp, 0644) mustWriteFile("comp/_hakurei", comp, 0644)
mustWriteFile("install.sh", []byte(`#!/bin/sh -e mustWriteFile("install.sh", []byte(`#!/bin/sh -e
cd "$(dirname -- "$0")" || exit 1 cd "$(dirname -- "$0")"
install -vDm0755 "bin/hakurei" "${DESTDIR}`+prefix+`/bin/hakurei" install -vDm0755 "bin/hakurei" "${DESTDIR}`+prefix+`/bin/hakurei"
install -vDm0755 "bin/sharefs" "${DESTDIR}`+prefix+`/bin/sharefs" install -vDm0755 "bin/sharefs" "${DESTDIR}`+prefix+`/bin/sharefs"
@@ -230,7 +230,7 @@ fi
install -vDm0644 "comp/_hakurei" "${DESTDIR}`+prefix+`/share/zsh/site-functions/_hakurei" install -vDm0644 "comp/_hakurei" "${DESTDIR}`+prefix+`/share/zsh/site-functions/_hakurei"
`), 0755) `), 0755)
mustWriteFromPath("README.md", "README.md", 0) mustWriteFromPath("LICENSE", "LICENSE", 0)
mustWriteFile("hsurc.default", []byte("1000 0"), 0400) mustWriteFile("hsurc.default", []byte("1000 0"), 0400)
mustWriteFromPath("bin/hsu", filepath.Join(s, "hsu"), 04511) mustWriteFromPath("bin/hsu", filepath.Join(s, "hsu"), 04511)
for _, name := range []string{ for _, name := range []string{
+18
View File
@@ -11,6 +11,7 @@ import (
"os/user" "os/user"
"strconv" "strconv"
"sync" "sync"
"syscall"
"time" "time"
"hakurei.app/check" "hakurei.app/check"
@@ -372,6 +373,23 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
Flag(&flagNoStore, "no-store", command.BoolFlag(false), "Do not attempt to match from active instances") Flag(&flagNoStore, "no-store", command.BoolFlag(false), "Do not attempt to match from active instances")
} }
c.NewCommand("kill", "Terminate an active instance", func(args []string) error {
if len(args) != 1 {
log.Fatal("kill requires 1 argument")
}
var sc hst.Paths
env.CopyPaths().Copy(&sc, new(outcome.Hsu).MustID(nil))
entry := tryIdentifier(msg, args[0], outcome.NewStore(&sc))
if entry == nil {
log.Fatalf("%q does not match any active instance", args[0])
}
if err := syscall.Kill(entry.PID, syscall.SIGTERM); err != nil {
log.Fatalf("cannot terminate %s: %v", entry.ID.String(), err)
}
return errSuccess
})
{ {
var flagShort bool var flagShort bool
c.NewCommand("ps", "List active instances", func(args []string) error { c.NewCommand("ps", "List active instances", func(args []string) error {
+1
View File
@@ -25,6 +25,7 @@ commands:
run Load and start container from configuration file run Load and start container from configuration file
exec Configure and start a permissive container exec Configure and start a permissive container
show Show live or local instance configuration show Show live or local instance configuration
kill Terminate an active instance
ps List active instances ps List active instances
version Display version information version Display version information
license Show full license text license Show full license text
+4
View File
@@ -1196,6 +1196,10 @@ func main() {
if w, ok := err.(interface{ Unwrap() []error }); !ok { if w, ok := err.(interface{ Unwrap() []error }); !ok {
log.Fatal(err) log.Fatal(err)
} else { } else {
if _, ok = w.(pkg.InputError); ok {
log.Fatal(w)
}
errs := w.Unwrap() errs := w.Unwrap()
for i, e := range errs { for i, e := range errs {
if i == len(errs)-1 { if i == len(errs)-1 {
+2 -5
View File
@@ -118,11 +118,8 @@ func TestExec(t *testing.T) {
[]string{"testtool"}, []string{"testtool"},
pkg.MustPath("/proc/nonexistent", false, failingArtifact), pkg.MustPath("/proc/nonexistent", false, failingArtifact),
), nil, nil, pkg.WNew, &pkg.DependencyCureError{ ), nil, nil, pkg.WNew, pkg.InputError{
{ failingArtifact: stub.UniqueError(0xcafe),
A: failingArtifact,
Err: stub.UniqueError(0xcafe),
},
}}, }},
{"invalid paths", pkg.NewExec( {"invalid paths", pkg.NewExec(
+48 -92
View File
@@ -15,10 +15,10 @@ import (
"hash" "hash"
"io" "io"
"io/fs" "io/fs"
"iter"
"maps" "maps"
"math" "math"
"os" "os"
"os/signal"
"path/filepath" "path/filepath"
"runtime" "runtime"
"slices" "slices"
@@ -654,10 +654,10 @@ type pendingArtifactDep struct {
// if curing succeeds. // if curing succeeds.
resP *cureRes resP *cureRes
// Address of result error slice populated during [Cache.Cure], dereferenced // Address of result error map populated during [Cache.Cure], dereferenced
// after acquiring errsMu if curing fails. No additional action is taken, // after acquiring errsMu if curing fails. No additional action is taken,
// [Cache] and its caller are responsible for further error handling. // [Cache] and its caller are responsible for further error handling.
errs *DependencyCureError errs InputError
// Address of mutex synchronising access to errs. // Address of mutex synchronising access to errs.
errsMu *sync.Mutex errsMu *sync.Mutex
@@ -1721,109 +1721,61 @@ retry:
goto retry goto retry
} }
// CureError wraps a non-nil error returned attempting to cure an [Artifact]. // An InputError describes inputs of a [FloodArtifact] which had failed to cure.
type CureError struct { type InputError map[Artifact]error
A Artifact
Err error
}
// Unwrap returns the underlying error. // unwrap returns an iterator over sorted, deduplicated [Artifact] and their
func (e *CureError) Unwrap() error { return e.Err } // corresponding identifier.
func (e InputError) unwrap() iter.Seq2[Artifact, unique.Handle[ID]] {
ir := NewIR()
// Error returns the error message from the underlying Err. type input struct {
func (e *CureError) Error() string { return e.Err.Error() } a Artifact
id unique.Handle[ID]
// A DependencyCureError wraps errors returned while curing dependencies.
type DependencyCureError []*CureError
// unwrapM recursively expands underlying errors into a caller-supplied map.
func (e *DependencyCureError) unwrapM(
ctx context.Context,
ir *IRCache,
me map[unique.Handle[ID]]*CureError,
) {
for _, err := range *e {
if ctx.Err() != nil {
break
}
id := ir.Ident(err.A)
if _, ok := me[id]; ok {
continue
}
if _e, ok := err.Err.(*DependencyCureError); ok {
_e.unwrapM(ctx, ir, me)
continue
}
me[id] = err
} }
} p := make([]input, 0, len(e))
for a := range e {
// unwrap recursively expands and deduplicates underlying errors. p = append(p, input{a, ir.Ident(a)})
func (e *DependencyCureError) unwrap(
ctx context.Context,
ir *IRCache,
) DependencyCureError {
me := make(map[unique.Handle[ID]]*CureError)
e.unwrapM(ctx, ir, me)
type ent struct {
id unique.Handle[ID]
err *CureError
}
errs := make([]*ent, 0, len(me))
for id, err := range me {
errs = append(errs, &ent{id, err})
} }
var identBuf [2]ID var identBuf [2]ID
slices.SortFunc(errs, func(a, b *ent) int { slices.SortFunc(p, func(a, b input) int {
identBuf[0], identBuf[1] = a.id.Value(), b.id.Value() identBuf[0], identBuf[1] = a.id.Value(), b.id.Value()
return slices.Compare(identBuf[0][:], identBuf[1][:]) return slices.Compare(identBuf[0][:], identBuf[1][:])
}) })
p = slices.CompactFunc(p, func(a, b input) bool { return a.id == b.id })
_errs := make(DependencyCureError, len(errs)) return func(yield func(Artifact, unique.Handle[ID]) bool) {
for i, v := range errs { for _, i := range p {
_errs[i] = v.err if !yield(i.a, i.id) {
return
}
}
} }
return _errs
} }
// Unwrap returns a deduplicated slice of underlying errors. // Error returns a user-facing, deterministic text representation of e.
func (e *DependencyCureError) Unwrap() []error { func (e InputError) Error() string {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
errs := e.unwrap(ctx, NewIR())
_errs := make([]error, len(errs))
for i, err := range errs {
_errs[i] = err
}
return _errs
}
// Error returns a user-facing multiline error message.
func (e *DependencyCureError) Error() string {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
ir := NewIR()
errs := e.unwrap(ctx, ir)
if len(errs) == 0 {
return "invalid dependency cure outcome"
}
var buf strings.Builder var buf strings.Builder
buf.WriteString("errors curing dependencies:") buf.WriteString("errors curing inputs:")
for _, err := range errs { for a, id := range e.unwrap() {
buf.WriteString("\n\t" + buf.WriteString("\n\t")
reportName(err.A, ir.Ident(err.A)) + ": " + buf.WriteString(reportName(a, id))
err.Error()) buf.WriteString(": ")
} buf.WriteString(e[a].Error())
if ctx.Err() != nil {
buf.WriteString("\nerror resolution cancelled")
} }
return buf.String() return buf.String()
} }
// Unwrap returns a slice of underlying errors sorted by identifier.
func (e InputError) Unwrap() []error {
errs := make([]error, 0, len(e))
for a := range e.unwrap() {
errs = append(errs, e[a])
}
return errs
}
// enterCure must be called before entering an [Artifact] implementation. // enterCure must be called before entering an [Artifact] implementation.
func (c *Cache) enterCure(a Artifact, curesExempt bool) error { func (c *Cache) enterCure(a Artifact, curesExempt bool) error {
if c.attr.Notify != nil { if c.attr.Notify != nil {
@@ -2023,7 +1975,7 @@ func (c *Cache) cureMany(
wg.Add(len(inputs)) wg.Add(len(inputs))
var mask []bool var mask []bool
res := make([]cureRes, len(inputs)) res := make([]cureRes, len(inputs))
errs := make(DependencyCureError, 0, len(inputs)) errs := make(InputError)
var errsMu sync.Mutex var errsMu sync.Mutex
if shallow { if shallow {
mask = make([]bool, len(inputs)) mask = make([]bool, len(inputs))
@@ -2042,13 +1994,13 @@ func (c *Cache) cureMany(
continue continue
} }
} }
pending := pendingArtifactDep{d, &res[i], &errs, &errsMu, &wg} pending := pendingArtifactDep{d, &res[i], errs, &errsMu, &wg}
go pending.cure(c) go pending.cure(c)
} }
wg.Wait() wg.Wait()
if len(errs) > 0 { if len(errs) > 0 {
return mask, &errs return mask, errs
} }
for i, p := range res { for i, p := range res {
if shallow && mask[i] { if shallow && mask[i] {
@@ -2651,7 +2603,11 @@ func (pending *pendingArtifactDep) cure(c *Cache) {
} }
pending.errsMu.Lock() pending.errsMu.Lock()
*pending.errs = append(*pending.errs, &CureError{pending.a, err}) if errs, ok := err.(InputError); ok {
maps.Copy(pending.errs, errs)
} else {
pending.errs[pending.a] = err
}
pending.errsMu.Unlock() pending.errsMu.Unlock()
} }
+42 -59
View File
@@ -861,14 +861,11 @@ func TestCache(t *testing.T) {
cure: func(f *pkg.FContext) error { cure: func(f *pkg.FContext) error {
panic("attempting to cure impossible artifact") panic("attempting to cure impossible artifact")
}, },
}, nil, nil, pkg.WNew, &pkg.DependencyCureError{ }, nil, nil, pkg.WNew, pkg.InputError{
{ failingFile: struct {
A: failingFile, _ []byte
Err: struct { stub.UniqueError
_ []byte }{UniqueError: 0xbad},
stub.UniqueError
}{UniqueError: 0xbad},
},
}}, }},
}) })
@@ -1949,7 +1946,7 @@ errors during scrub:
} }
} }
func TestDependencyCureError(t *testing.T) { func TestInputError(t *testing.T) {
t.Parallel() t.Parallel()
makeIdent := func(ident ...byte) pkg.Artifact { makeIdent := func(ident ...byte) pkg.Artifact {
@@ -1962,56 +1959,40 @@ func TestDependencyCureError(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
err pkg.DependencyCureError err pkg.InputError
want string want string
unwrap []error unwrap []error
}{ }{
{"simple", pkg.DependencyCureError{ {"simple", pkg.InputError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)}, makeIdent(0xff, 9): stub.UniqueError(0xbad09),
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, makeIdent(0xff, 0): stub.UniqueError(0xbad00),
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)}, makeIdent(0xff, 0xf): stub.UniqueError(0xbad0f),
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)}, makeIdent(0xff, 1): stub.UniqueError(0xbad01),
}, `errors curing dependencies: }, `errors curing inputs:
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite _wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite _wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite _wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{ _w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, stub.UniqueError(0xbad00),
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)}, stub.UniqueError(0xbad01),
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)}, stub.UniqueError(0xbad09),
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)}, stub.UniqueError(0xbad0f),
}}, }},
{"dedup", pkg.DependencyCureError{ {"dedup", pkg.InputError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)}, makeIdent(0xff, 9): stub.UniqueError(0xbad09),
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, makeIdent(0xff, 9): stub.UniqueError(0xbad09),
{A: makeIdent(0xff, 0xfd), Err: &pkg.DependencyCureError{ makeIdent(0xff, 9): stub.UniqueError(0xbad09),
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)}, makeIdent(0xff, 0): stub.UniqueError(0xbad00),
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{ makeIdent(0xff, 0): stub.UniqueError(0xbad00),
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)}, makeIdent(0xff, 1): stub.UniqueError(0xbad01),
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, }, `errors curing inputs:
}},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
}},
{A: makeIdent(0xff, 0xff), Err: &pkg.DependencyCureError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
}},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
}},
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
}, `errors curing dependencies:
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite _wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite _wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite _wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite`, []error{
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{ stub.UniqueError(0xbad00),
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, stub.UniqueError(0xbad01),
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)}, stub.UniqueError(0xbad09),
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
}}, }},
} }
for _, tc := range testCases { for _, tc := range testCases {
@@ -2055,19 +2036,21 @@ func (a earlyFailureF) Cure(*pkg.FContext) error {
func BenchmarkEarlyDCE(b *testing.B) { func BenchmarkEarlyDCE(b *testing.B) {
msg := message.New(log.New(os.Stderr, "dce: ", 0)) msg := message.New(log.New(os.Stderr, "dce: ", 0))
msg.SwapVerbose(testing.Verbose()) msg.SwapVerbose(testing.Verbose())
c, err := pkg.Open(b.Context(), msg, check.MustAbs(b.TempDir()), nil)
if err != nil {
b.Fatal(err)
}
_, _, err = c.Cure(earlyFailureF(8))
if !errors.Is(err, stub.UniqueError(0xcafe)) {
b.Fatalf("Cure: error = %v", err)
}
c.Close()
dce := err.(*pkg.DependencyCureError)
for b.Loop() { for b.Loop() {
dce.Unwrap() b.StopTimer()
c, err := pkg.Open(b.Context(), msg, check.MustAbs(b.TempDir()), nil)
if err != nil {
b.Fatal(err)
}
b.StartTimer()
_, _, err = c.Cure(earlyFailureF(8))
b.StopTimer()
if !errors.Is(err, stub.UniqueError(0xcafe)) {
b.Fatalf("Cure: error = %v", err)
}
c.Close()
b.StartTimer()
} }
} }
+86 -6
View File
@@ -6,6 +6,7 @@ import (
"errors" "errors"
"io" "io"
"strconv" "strconv"
"strings"
"text/scanner" "text/scanner"
) )
@@ -302,6 +303,7 @@ func (ScanError) Error() string {
// Parse parses expressions from r. // Parse parses expressions from r.
func Parse(r io.Reader) (e []any, err error) { func Parse(r io.Reader) (e []any, err error) {
r = insertDelimiters(r)
var p parser var p parser
p.s.Init(r) p.s.Init(r)
@@ -311,12 +313,7 @@ func Parse(r io.Reader) (e []any, err error) {
scanner.ScanRawStrings | scanner.ScanRawStrings |
scanner.ScanComments | scanner.ScanComments |
scanner.SkipComments scanner.SkipComments
p.s.IsIdentRune = func(ch rune, i int) bool { p.s.IsIdentRune = isIdentRune
if i == 0 && ch >= '0' && ch <= '9' {
return false
}
return ch > 0 && ch < rune(len(idents)) && idents[ch]
}
defer func() { defer func() {
v := recover() v := recover()
@@ -346,3 +343,86 @@ func Parse(r io.Reader) (e []any, err error) {
} }
return return
} }
func isIdentRune(ch rune, i int) bool {
if i == 0 && ch >= '0' && ch <= '9' {
return false
}
return ch > 0 && ch < rune(len(idents)) && idents[ch]
}
func insertDelimiters(r io.Reader) io.Reader {
var s scanner.Scanner
s.Init(r)
s.Mode = scanner.ScanIdents |
scanner.ScanInts |
scanner.ScanStrings |
scanner.ScanRawStrings |
scanner.ScanComments |
scanner.SkipComments
s.Whitespace = 0
s.IsIdentRune = isIdentRune
var b strings.Builder
nldelim := false
delim := new(runeStack)
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
switch tok {
case '{', '[':
nldelim = false
if tok == '{' {
delim.Push(';')
} else {
delim.Push(',')
}
b.WriteRune(tok)
case scanner.String, scanner.RawString, scanner.Int, scanner.Ident:
b.WriteString(s.TokenText())
nldelim = true
case '+', ':', '=', ',', ';':
nldelim = false
b.WriteRune(tok)
case '\n':
if nldelim {
b.WriteRune(delim.Peek())
nldelim = false
}
case '}', ']':
if nldelim {
b.WriteRune(delim.Peek())
}
delim.Pop()
nldelim = true
b.WriteRune(tok)
default:
b.WriteRune(tok)
}
}
return strings.NewReader(b.String())
}
type runeStack struct {
arr []rune
}
func (s *runeStack) Push(r rune) {
s.arr = append(s.arr, r)
}
func (s *runeStack) Peek() rune {
if s.Length() > 0 {
return s.arr[s.Length()-1]
}
return '\n'
}
func (s *runeStack) Pop() rune {
v := s.Peek()
if s.Length() > 1 {
s.arr = s.arr[:s.Length()-1]
} else {
s.arr = make([]rune, 0)
}
return v
}
func (s *runeStack) Length() int {
return len(s.arr)
}
+191 -5
View File
@@ -11,7 +11,10 @@ import (
) )
//go:embed testdata/gcc.az //go:embed testdata/gcc.az
var sample string var gccSample string
//go:embed testdata/mesa.az
var mesaSample string
func TestParse(t *testing.T) { func TestParse(t *testing.T) {
t.Parallel() t.Parallel()
@@ -61,8 +64,57 @@ func TestParse(t *testing.T) {
{"missing array delimiter", `[ v0 v1 ]`, nil, TokenError{',', scanner.Ident}}, {"missing array delimiter", `[ v0 v1 ]`, nil, TokenError{',', scanner.Ident}},
{"truncated array", `[ "\x00"`, nil, {"truncated array", `[ "\x00"`, nil,
ExprError(scanner.EOF)}, ExprError(scanner.EOF)},
{"array of func", "[\nf {\n v = v\n v2 =\n v2\n }\n g {\n w = w\n w2 = w2\n}\n]\n", []any{Array{
{"gcc", sample, []any{Func{ Val{Func{
Ident: Ident("f"),
Args: []Arg{
{K: []Ident{Ident("v")}, V: Val{Ident("v")}},
{K: []Ident{Ident("v2")}, V: Val{Ident("v2")}},
},
}},
Val{Func{
Ident: Ident("g"),
Args: []Arg{
{K: []Ident{Ident("w")}, V: Val{Ident("w")}},
{K: []Ident{Ident("w2")}, V: Val{Ident("w2")}},
},
}},
}}, nil},
{"mixed semicolons and newlines", `
f {
a = 4;
b = 2
c = [
a,
b
c
d, e
]
d = {
"a": b;
"c": d
}; e = 2
}`,
[]any{Func{
Ident: Ident("f"),
Args: []Arg{
{K: []Ident{Ident("a")}, V: Val{Int(4)}},
{K: []Ident{Ident("b")}, V: Val{Int(2)}},
{K: []Ident{Ident("c")}, V: Val{Array{
Val{Ident("a")},
Val{Ident("b")},
Val{Ident("c")},
Val{Ident("d")},
Val{Ident("e")},
}}},
{K: []Ident{Ident("d")}, V: Val{[]KV{
{K: String("a"), V: Val{Ident("b")}},
{K: String("c"), V: Val{Ident("d")}},
}}},
{K: []Ident{Ident("e")}, V: Val{Int(2)}},
},
}}, nil},
{"gcc", gccSample, []any{Func{
Ident: Ident("gcc"), Ident: Ident("gcc"),
Package: true, Package: true,
@@ -139,6 +191,140 @@ func TestParse(t *testing.T) {
}}}, }}},
}, },
}}, nil}, }}, nil},
{"mesa", mesaSample, []any{Func{
Ident: Ident("mesa"),
Package: true,
Args: []Arg{
{K: []Ident{Ident("description")}, V: Val{String("open source implementations of OpenGL, OpenGL ES, Vulkan, OpenCL, and more")}},
{K: []Ident{Ident("website")}, V: Val{String("https://mesa3d.org")}},
{K: []Ident{Ident("anitya")}, V: Val{Int(1970)}},
{K: []Ident{Ident("latest")}, V: Val{Ident("anityaFallback")}},
{K: []Ident{Ident("version")}, V: Val{String("26.2.0")}, R: true},
{K: []Ident{Ident("source")}, V: Val{Func{
Ident: Ident("remoteGitLab"),
Args: []Arg{
{K: []Ident{Ident("domain")}, V: Val{String("gitlab.freedesktop.org")}},
{K: []Ident{Ident("suffix")}, V: Val{String("mesa/mesa")}},
{K: []Ident{Ident("ref")}, V: Val{String("mesa-"), Ident("version")}},
{K: []Ident{Ident("checksum")}, V: Val{String("UPnIdpo5wUsE938GXY-YyYDzfF62enRoEzCYRyLLPvzBhBbP4wZ8nDiKsjivcs5v")}},
},
}}},
{K: []Ident{Ident("exec")}, V: Val{Func{Ident: Ident("meson"), Args: []Arg{
{K: []Ident{Ident("setup")}, V: Val{[]KV{
{K: String("platforms"), V: Val{String("x11,wayland")}},
{K: String("video-codecs"), V: Val{String("all")}},
{K: String("glvnd"), V: Val{String("enabled")}},
{K: String("gbm"), V: Val{String("enabled")}},
{K: String("egl"), V: Val{String("enabled")}},
{K: String("gallium-drivers"), V: Val{Func{
Ident: Ident("join"),
Args: []Arg{
{K: []Ident{Ident("elems")}, V: Val{Array{
Val{String("asahi")},
Val{String("crocus")},
Val{String("etnaviv")},
Val{String("freedreno")},
Val{String("i915")},
Val{String("iris")},
Val{String("lima")},
Val{String("llvmpipe")},
Val{String("nouveau")},
Val{String("panfrost")},
Val{String("r300")},
Val{String("r600")},
Val{String("radeonsi")},
Val{String("softpipe")},
Val{String("svga")},
Val{String("tegra")},
Val{String("v3d")},
Val{String("vc4")},
Val{String("virgl")},
Val{String("zink")}}}},
{K: []Ident{Ident("sep")}, V: Val{String(",")}},
},
}}},
{K: String("vulkan-drivers"), V: Val{Func{
Ident: Ident("join"),
Args: []Arg{
{K: []Ident{Ident("elems")}, V: Val{Array{
Val{String("amd")},
Val{String("broadcom")},
Val{String("freedreno")},
Val{String("intel")},
Val{String("intel_hasvk")},
Val{String("panfrost")},
Val{String("swrast")},
Val{String("virtio")},
Val{String("imagination")},
Val{String("asahi")},
Val{String("gfxstream")},
}}},
{K: []Ident{Ident("sep")}, V: Val{String(",")}}},
}}},
{K: String("vulkan-layers"), V: Val{Func{
Ident: Ident("join"),
Args: []Arg{
{K: []Ident{Ident("elems")}, V: Val{Array{
Val{String("device-select")},
Val{String("intel-nullhw")},
Val{String("overlay")},
Val{String("screenshot")},
Val{String("anti-lag")},
Val{String("vram-report-limit")},
}}},
{K: []Ident{Ident("sep")}, V: Val{String(",")}}},
}}},
{K: String("freedreno-kmds"), V: Val{String("msm,virtio")}},
{K: String("amdgpu-virtio"), V: Val{String("true")}}},
}},
}}}},
{K: []Ident{Ident("inputs")}, V: Val{Array{
Val{Ident("m4")},
Val{Ident("python-packaging")},
Val{Ident("python-mako")},
Val{Ident("python-pyyaml")},
Val{Ident("python-pycparser")},
Val{Ident("glslang")},
Val{Ident("spirv-llvm-translator")},
Val{Ident("zlib")},
Val{Ident("zstd")},
Val{Ident("gzip")},
Val{Ident("ncurses")},
Val{Ident("libglvnd")},
Val{Ident("libexpat")},
Val{Ident("libva")},
Val{Ident("libdrm")},
Val{Ident("elfutils")},
Val{Ident("bison")},
Val{Ident("flex")},
Val{Ident("lm_sensors")},
Val{Ident("libconfig")},
Val{Ident("libdisplay-info")},
Val{Ident("wayland")},
Val{Ident("wayland-protocols")},
Val{Ident("libxshmfence")},
Val{Ident("libXxf86vm")},
Val{Ident("libXrandr")},
Val{Ident("libxcb-keysyms")},
Val{Ident("libpng")},
Val{Ident("libarchive")},
Val{Ident("kernel-headers")},
}}},
{K: []Ident{Ident("runtime")}, V: Val{Array{
Val{Ident("llvm")},
Val{Ident("libdrm")},
Val{Ident("elfutils")},
Val{Ident("lm_sensors")},
Val{Ident("libdisplay-info")},
Val{Ident("wayland")},
Val{Ident("libxshmfence")},
Val{Ident("libXxf86vm")},
Val{Ident("libXrandr")},
Val{Ident("libxcb-keysyms")},
Val{Ident("libpng")}}}},
},
}}, nil},
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
@@ -156,14 +342,14 @@ func TestParse(t *testing.T) {
} }
func BenchmarkParse(b *testing.B) { func BenchmarkParse(b *testing.B) {
r := strings.NewReader(sample) r := strings.NewReader(gccSample)
for b.Loop() { for b.Loop() {
if _, err := Parse(r); err != nil { if _, err := Parse(r); err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.StopTimer() b.StopTimer()
r.Reset(sample) r.Reset(gccSample)
b.StartTimer() b.StartTimer()
} }
} }
+59 -6
View File
@@ -12,7 +12,7 @@ import (
// Value are types supported by the language. // Value are types supported by the language.
type Value interface { type Value interface {
bool | int64 | string | []string | []int64 | [][2]string bool | int64 | string | []string | []int64 | [][2]string | Nil
} }
type ( type (
@@ -33,6 +33,29 @@ type (
F func(args FArgs) (v any, set bool, err error) F func(args FArgs) (v any, set bool, err error)
V map[unique.Handle[Ident]]any V map[unique.Handle[Ident]]any
} }
// Nil represents an untyped nil.
Nil struct{}
// AString represents an argument string that may be nil.
AString struct {
V string
Nil bool
}
)
// NilError is returned for an invalid nil assignment.
type NilError struct{ reflect.Type }
func (e NilError) Error() string {
return fmt.Sprintf("attempting to assign nil to %s", e.Type)
}
var (
// nilStringV is the [reflect.Value] of an Azalea nil assigned to an [AString].
nilStringV = reflect.ValueOf(AString{Nil: true})
// nilStringT is the [reflect.Type] of nilStringV.
nilStringT = nilStringV.Type()
) )
// Apply applies named arguments and rejects unused arguments. // Apply applies named arguments and rejects unused arguments.
@@ -50,8 +73,8 @@ func (args FArgs) Apply(v map[unique.Handle[Ident]]any) error {
} }
return UndefinedError(arg.K.Value()) return UndefinedError(arg.K.Value())
} }
err := storeE(r, arg.V)
if err != nil { if err := storeE(r, arg.V); err != nil {
return err return err
} }
} }
@@ -115,11 +138,38 @@ func (e TypeError) Is(err error) bool {
} }
// storeE is a convenience function to set the value of a result pointer. // storeE is a convenience function to set the value of a result pointer.
func storeE(rp any, r any) error { func storeE(rp, r any) error {
pv := reflect.ValueOf(rp).Elem() pv := reflect.ValueOf(rp).Elem()
pt := pv.Type()
as := nilStringT.AssignableTo(pt)
if r == (Nil{}) {
switch kind := pt.Kind(); kind {
case reflect.Bool, reflect.String:
return NilError{pt}
default:
if rv, ok := rp.(*any); ok && !reflect.ValueOf(*rv).IsValid() {
*rv = Nil{}
} else if as {
pv.Set(nilStringV)
} else {
pv.SetZero()
}
return nil
}
}
v := reflect.ValueOf(r) v := reflect.ValueOf(r)
pt, vt := pv.Type(), v.Type() if vt := v.Type(); !vt.AssignableTo(pt) {
if !vt.AssignableTo(pt) { if as {
var asv AString
if err := storeE(&asv.V, r); err != nil {
return err
}
pv.Set(reflect.ValueOf(asv))
return nil
}
return TypeError{vt, pt} return TypeError{vt, pt}
} }
pv.Set(v) pv.Set(v)
@@ -226,6 +276,9 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
case "false": case "false":
store(rp, false) store(rp, false)
return true return true
case "nil":
store(rp, Nil{})
return true
default: default:
return evaluateAny(d, s, v, rp) return evaluateAny(d, s, v, rp)
} }
+71 -7
View File
@@ -100,15 +100,79 @@ func TestEvaluate(t *testing.T) {
Err: UndefinedError("f"), Err: UndefinedError("f"),
}}, }},
{"error wrap deep", `f { v = nil; }`, makeStackCheck(func( {"error wrap deep", `f { v = nonexistent; }`, makeStackCheck(func(
FArgs, FArgs,
) (any, error) { ) (any, error) {
panic("unreachable") panic("unreachable")
}), "", EvaluationError{ }), "", EvaluationError{
Expr: Ident("nil"), Expr: Ident("nonexistent"),
Err: UndefinedError("nil"), Err: UndefinedError("nonexistent"),
}}, }},
{"nil", `f { v = nil; }`, checkArgs(FArgs{
{K: unique.Make(Ident("v")), V: Nil{}},
}), "\xfd", nil},
{"apply nil string", `f { v = nil; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
var s string
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &s,
})
v = s
return
}), "", EvaluationError{
Expr: Func{
Ident: Ident("f"),
Args: []Arg{
{K: []Ident{"v"}, V: Val{Ident("nil")}},
},
},
Err: NilError{Type: reflect.TypeFor[string]()},
}},
{"apply nil AString", `f { v = nil; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
s := AString{}
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &s,
})
v = s.V
if !s.Nil {
err = fmt.Errorf("got non-nil string %q", s.V)
}
return
}), "", nil},
{"apply AString", `f { v = "\xfd"; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
s := AString{}
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &s,
})
v = s.V
if s.Nil {
err = fmt.Errorf("unexpected nil %q", s.V)
}
return
}), "\xfd", nil},
{"apply nil", `f { v = nil; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
s := make([]struct{}, 9)
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &s,
})
if s != nil {
err = fmt.Errorf("got non-nil value %#v", s)
}
return
}), "", nil},
{"common inputs", `package name { inputs, v = []; }`, nil, "", EvaluationError{ {"common inputs", `package name { inputs, v = []; }`, nil, "", EvaluationError{
Expr: Func{ Expr: Func{
Ident: Ident("name"), Ident: Ident("name"),
@@ -214,8 +278,8 @@ func TestEvaluate(t *testing.T) {
} }
var errEquals bool var errEquals bool
if _, ok := errors.AsType[TypeError](err); ok { if e, ok := errors.AsType[TypeError](err); ok {
errEquals = errors.Is(err, tc.err) errEquals = e.Is(tc.err)
} else { } else {
errEquals = reflect.DeepEqual(err, tc.err) errEquals = reflect.DeepEqual(err, tc.err)
} }
@@ -230,7 +294,7 @@ func TestEvaluateGCC(t *testing.T) {
t.Parallel() t.Parallel()
var gcc Func var gcc Func
if e, err := Parse(strings.NewReader(sample)); err != nil { if e, err := Parse(strings.NewReader(gccSample)); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
gcc = e[0].(Func) gcc = e[0].(Func)
@@ -357,7 +421,7 @@ func TestEvaluateGCC(t *testing.T) {
func BenchmarkEvaluate(b *testing.B) { func BenchmarkEvaluate(b *testing.B) {
var gcc Func var gcc Func
if e, err := Parse(strings.NewReader(sample)); err != nil { if e, err := Parse(strings.NewReader(gccSample)); err != nil {
b.Fatal(err) b.Fatal(err)
} else { } else {
gcc = e[0].(Func) gcc = e[0].(Func)
+35 -35
View File
@@ -1,19 +1,19 @@
package gcc { package gcc {
description = "The GNU Compiler Collection"; description = "The GNU Compiler Collection"
website = "https://www.gnu.org/software/gcc"; website = "https://www.gnu.org/software/gcc"
anitya = 6502; anitya = 6502
version# = "16.1.0"; version# = "16.1.0"
source = remoteTar { source = remoteTar {
url = "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+ url = "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+
"gcc-"+version+"/gcc-"+version+".tar.gz"; "gcc-"+version+"/gcc-"+version+".tar.gz"
checksum = "4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K"; checksum = "4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K"
compress = gzip; compress = gzip
}; }
patches = [ patches = [
"musl-off64_t-loff_t.patch", "musl-off64_t-loff_t.patch"
"musl-legacy-lfs.patch", "musl-legacy-lfs.patch"
]; ]
// GCC spends most of its time in its many configure scripts, however // GCC spends most of its time in its many configure scripts, however
// it also saturates the CPU for a consequential amount of time. // it also saturates the CPU for a consequential amount of time.
@@ -21,37 +21,37 @@ package gcc {
exec = make { exec = make {
configure = { configure = {
"disable-multilib"; "disable-multilib"
"enable-default-pie"; "enable-default-pie"
"disable-nls"; "disable-nls"
"with-gnu-as"; "with-gnu-as"
"with-gnu-ld"; "with-gnu-ld"
"with-system-zlib"; "with-system-zlib"
"enable-languages": "c,c++,go"; "enable-languages": "c,c++,go"
"with-native-system-header-dir": "/system/include"; "with-native-system-header-dir": "/system/include"
"with-multilib-list": arch { "with-multilib-list": arch {
amd64, arm64 = "''"; amd64, arm64 = "''"
default = unset; default = unset
}; }
}; }
make = [ make = [
"BOOT_CFLAGS='-O2 -g'", "BOOT_CFLAGS='-O2 -g'"
noop { key = value; } + "\x00", noop { key = value } + "\x00"
"bootstrap", "bootstrap"
]; ]
// This toolchain is hacked to pieces, it is not expected to ever work // This toolchain is hacked to pieces, it is not expected to ever work
// well in its current state. That does not matter as long as the // well in its current state. That does not matter as long as the
// toolchain it produces passes its own test suite. // toolchain it produces passes its own test suite.
skip-check = true; skip-check = true
}; }
inputs = [ inputs = [
binutils, binutils
mpc, mpc
zlib, zlib
libucontext, libucontext
kernel-headers, kernel-headers
]; ]
} }
+139
View File
@@ -0,0 +1,139 @@
package mesa {
description = "open source implementations of OpenGL, OpenGL ES, Vulkan, OpenCL, and more"
website = "https://mesa3d.org"
anitya = 1970
latest = anityaFallback
version# = "26.2.0"
source = remoteGitLab {
domain = "gitlab.freedesktop.org"
suffix = "mesa/mesa"
ref = "mesa-"+version
checksum = "UPnIdpo5wUsE938GXY-YyYDzfF62enRoEzCYRyLLPvzBhBbP4wZ8nDiKsjivcs5v"
}
exec = meson {
setup = {
"platforms": "x11,wayland"
"video-codecs": "all"
"glvnd": "enabled"
"gbm": "enabled"
"egl": "enabled"
"gallium-drivers": join {
elems = [
"asahi" // Apple AGX
"crocus" // Intel legacy
"etnaviv" // Vivante GPU designs (mostly NXP/Marvell SoCs)
"freedreno" // Qualcomm Adreno (all Qualcomm SoCs)
"i915" // Intel extra legacy
"iris" // new Intel (Broadwell+)
"lima" // ARM Mali 4xx
"llvmpipe" // software renderer
"nouveau" // Nvidia
"panfrost" // ARM Mali Midgard and up (T/G series)
"r300" // very old AMD
"r600" // less old AMD
"radeonsi" // new AMD (GCN+)
"softpipe" // older software renderer
"svga" // VMWare virtualized GPU
"tegra" // Nvidia Tegra SoCs
"v3d" // Broadcom VC5 (Raspberry Pi 4)
"vc4" // Broadcom VC4 (Raspberry Pi 0-3)
"virgl" // QEMU virtualized GPU (aka VirGL)
"zink" // generic OpenGL over Vulkan, experimental
// d3d12: WSL emulated GPU (aka Dozen)
// ethosu: accelerator
// rocket: accelerator
]
sep = ","
}
"vulkan-drivers": join {
elems = [
"amd" // AMD (aka RADV)
"broadcom" // Broadcom VC5 (Raspberry Pi 4, aka V3D)
"freedreno" // Qualcomm Adreno (all Qualcomm SoCs)
"intel" // new Intel (aka ANV)
"intel_hasvk" // Intel Haswell/Broadwell, "legacy" Vulkan driver (https://www.phoronix.com/news/Intel-HasVK-Drop-Dead-Code)
"panfrost" // ARM Mali Midgard and up (T/G series)
"swrast" // software renderer (aka Lavapipe)
"virtio" // QEMU virtualized GPU (aka VirGL)
"imagination" // PowerVR Rogue
"asahi" // Apple AGX
"gfxstream" // Android virtualized GPU
// nouveau: Nouveau (aka NVK), requires rust
// microsoft-experimental: WSL virtualized GPU (aka DZN/Dozen)
// kosmickrisp: macOS-specific
]
sep = ","
}
"vulkan-layers": join {
elems = [
"device-select"
"intel-nullhw"
"overlay"
"screenshot"
"anti-lag"
"vram-report-limit"
]
sep = ","
}
"freedreno-kmds": "msm,virtio"
"amdgpu-virtio": "true"
}
}
inputs = [
m4
python-packaging
python-mako
python-pyyaml
python-pycparser
glslang
spirv-llvm-translator
zlib
zstd
gzip
ncurses
libglvnd
libexpat
libva
libdrm
elfutils
bison
flex
lm_sensors
libconfig
libdisplay-info
wayland
wayland-protocols
libxshmfence
libXxf86vm
libXrandr
libxcb-keysyms
libpng
libarchive
kernel-headers
]
runtime = [
llvm
libdrm
elfutils
lm_sensors
libdisplay-info
wayland
libxshmfence
libXxf86vm
libXrandr
libxcb-keysyms
libpng
]
}
+1 -1
View File
@@ -39,7 +39,7 @@ package acl {
exec = make { exec = make {
// makes assumptions about uid_map/gid_map // makes assumptions about uid_map/gid_map
skipCheck = true; check = nil;
}; };
inputs = [ attr, kernel-headers ]; inputs = [ attr, kernel-headers ];
+3 -3
View File
@@ -15,9 +15,9 @@ package awk {
chmod = true; chmod = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
make = [ "YACC='yacc -d -b awkgram'" ]; make = [ "YACC='yacc -d -b awkgram'" ];
preCheck = "install -vD a.out /system/bin/awk\n"; preCheck = "install -vD a.out /system/bin/awk\n";
install = "install -vD a.out /work/system/bin/awk"; install = "install -vD a.out /work/system/bin/awk";
+1 -1
View File
@@ -12,7 +12,7 @@ package bison {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
check = [ check = [
"TESTSUITEFLAGS=" + jobsFlagE + "' " + skipGNUTests { "TESTSUITEFLAGS=" + jobsFlagE + "' " + skipGNUTests {
tests = [ tests = [
+1 -1
View File
@@ -19,6 +19,6 @@ package byacc {
chmod = true; chmod = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
}; };
} }
+4 -7
View File
@@ -15,13 +15,10 @@ package bzip2 {
enterSource = true; enterSource = true;
exec = make { exec = make {
skipConfigure = true; chdir = false;
skipCheck = true; configure = nil;
inPlace = true; make = [ "CC=cc" ];
check = nil;
make = [
"CC=cc",
];
install = "make PREFIX=/work/system install"; install = "make PREFIX=/work/system install";
}; };
} }
+1 -1
View File
@@ -27,7 +27,7 @@ package cairo {
// runs the entire test suite in a single meson test // runs the entire test suite in a single meson test
interactiveTest = true; interactiveTest = true;
// only works with specific dependency versions // only works with specific dependency versions
skipTest = true; test = false;
}; };
inputs = [ inputs = [
+1 -1
View File
@@ -20,7 +20,7 @@ package cmake {
chmod = true; chmod = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
configureName = "/usr/src/cmake/bootstrap"; configureName = "/usr/src/cmake/bootstrap";
configure = { configure = {
+1 -1
View File
@@ -19,7 +19,7 @@ package connman {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
dbus, dbus,
iptables, iptables,
+1 -1
View File
@@ -21,7 +21,7 @@ touch \
`; `;
exec = make { exec = make {
inPlace = true; chdir = false;
configureName = "../dist/configure"; configureName = "../dist/configure";
forceAutoconf = true; forceAutoconf = true;
configure = { configure = {
+2 -2
View File
@@ -41,11 +41,11 @@ package xdg-dbus-proxy {
website = "https://github.com/flatpak/xdg-dbus-proxy"; website = "https://github.com/flatpak/xdg-dbus-proxy";
anitya = 58434; anitya = 58434;
version# = "0.1.7"; version# = "0.1.8";
source = remoteGitHub { source = remoteGitHub {
suffix = "flatpak/xdg-dbus-proxy"; suffix = "flatpak/xdg-dbus-proxy";
tag = version; tag = version;
checksum = "UW5Pe-TP-XAaN-kTbxrkOQ7eYdmlAQlr2pdreLtPT0uwdAz-7rzDP8V_8PWuZBup"; checksum = "ygdW0EEvZ-_PJfnFTNoobITmRzqJecTinBsJd_iJQrRvzidwqESCjeNkB55smZ2y";
}; };
exec = meson { exec = meson {
+4 -4
View File
@@ -18,17 +18,17 @@ package elfutils {
]; ];
exec = make { exec = make {
// nonstandard glibc extension
skipCheck = true;
configure = { configure = {
"enable-deterministic-archives"; "enable-deterministic-archives";
}; };
// nonstandard glibc extension
check = nil;
}; };
inputs = [ inputs = [
m4, m4,
pkg-config, pkgconf,
zlib, zlib,
bzip2, bzip2,
+6 -6
View File
@@ -3,12 +3,12 @@ package firmware {
website = "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git"; website = "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git";
anitya = 141464; anitya = 141464;
version# = "20260622"; version# = "20260810";
source = remoteGitLab { source = remoteGitLab {
domain = "gitlab.com"; domain = "gitlab.com";
suffix = "kernel-firmware/linux-firmware"; suffix = "kernel-firmware/linux-firmware";
ref = version; ref = version;
checksum = "gpytkDM58EVjaUuryOekcekh_rWsfuv3S7LQxopHlNlVGmMsuqNwfug4BjgTgizE"; checksum = "XNUhz9QstaDKNegM3Bl0-TtZzpsvX7-E8WMnDCO7KBhBC6t_TxsdG05-ETdXynry";
}; };
// dedup creates temporary file // dedup creates temporary file
@@ -22,17 +22,17 @@ package firmware {
]; ];
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true; chdir = false;
inPlace = true;
configure = nil;
make = [ make = [
"DESTDIR=/work/system", "DESTDIR=/work/system",
"install-zst", "install-zst",
]; ];
// requires pre-commit // requires pre-commit
skipCheck = true; check = nil;
install = "make " + jobsFlagE + " " + loadFlagE + " DESTDIR=/work/system dedup"; install = "make " + jobsFlagE + " " + loadFlagE + " DESTDIR=/work/system dedup";
}; };
+1 -1
View File
@@ -18,7 +18,7 @@ package fontconfig {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
gettext, gettext,
gperf, gperf,
gzip, gzip,
+1 -1
View File
@@ -22,7 +22,7 @@ package fuse {
postCompile = "python3 -m pytest test/"; postCompile = "python3 -m pytest test/";
// this project uses pytest // this project uses pytest
skipTest = true; test = false;
}; };
inputs = [ inputs = [
+1 -1
View File
@@ -65,7 +65,7 @@ ln -s system/lib /work/
// This toolchain is hacked to pieces, it is not expected to ever work // This toolchain is hacked to pieces, it is not expected to ever work
// well in its current state. That does not matter as long as the // well in its current state. That does not matter as long as the
// toolchain it produces passes its own test suite. // toolchain it produces passes its own test suite.
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
+1 -1
View File
@@ -23,7 +23,7 @@ rm -f /system/bin/httpd
bin = [ "perl" ]; bin = [ "perl" ];
populateUsrBin = true; populateUsrBin = true;
exec = make { exec = make {
inPlace = true; chdir = false;
generate = "make configure"; generate = "make configure";
preMake = ` preMake = `
+9 -9
View File
@@ -19,7 +19,7 @@ chmod +w tests/test-c32ispunct.sh && echo '#!/bin/sh' > tests/test-c32ispunct.sh
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
}; };
inputs = [ inputs = [
@@ -114,7 +114,7 @@ package libtool {
exec = make { exec = make {
// _Z2a2c: symbol not found // _Z2a2c: symbol not found
skipEarlyStageCheck = true; checkEarly = false;
check = [ check = [
"TESTSUITEFLAGS=" + jobsFlagE, "TESTSUITEFLAGS=" + jobsFlagE,
@@ -142,7 +142,7 @@ package gzip {
exec = make { exec = make {
// dependency loop // dependency loop
skipCheck = true; check = nil;
}; };
} }
@@ -197,7 +197,7 @@ test_disable '#!/bin/sh' tests/cmp
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
}; };
} }
@@ -223,7 +223,7 @@ test_disable '#!/bin/sh' tests/need-filename
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
}; };
} }
@@ -334,7 +334,7 @@ package bash {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
configure = { configure = {
"without-bash-malloc"; "without-bash-malloc";
}; };
@@ -371,7 +371,7 @@ test_disable 'int main(){return 0;}' gnulib-tests/test-lchown.c
`; `;
exec = make { exec = make {
omitDefaults = true; defaults = false;
configure = { configure = {
"enable-single-binary": "symlinks"; "enable-single-binary": "symlinks";
}; };
@@ -436,7 +436,7 @@ package texinfo {
exec = make { exec = make {
// nonstandard glibc extension // nonstandard glibc extension
skipCheck = true; check = nil;
}; };
inputs = [ perl ]; inputs = [ perl ];
@@ -648,7 +648,7 @@ package mpc {
enterSource = true; enterSource = true;
exec = make { exec = make {
inPlace = true; chdir = false;
generate = "autoreconf -vfi"; generate = "autoreconf -vfi";
}; };
+1 -1
View File
@@ -47,7 +47,7 @@ echo 'int main(){return 0;}' > tests/mini-dtls-fragments.c
bison, bison,
gettext, gettext,
gperf, gperf,
pkg-config, pkgconf,
python, python,
texinfo, texinfo,
-135
View File
@@ -1,135 +0,0 @@
From 06f90ebfa6f3e0a744584513e2786988b26569da Mon Sep 17 00:00:00 2001
From: Damien Neil <dneil@google.com>
Date: Wed, 08 Jul 2026 11:11:48 -0700
Subject: [PATCH] os: properly handle trailing / in Root.MkdirAll
MkdirAll("dir/") should create "dir", not return an error.
Fixes #80308
Change-Id: I75458c30b6cb94be3a3d368f6024caef6a6a6964
---
diff --git a/src/os/root_noopenat.go b/src/os/root_noopenat.go
index 228b580..a84e952 100644
--- a/src/os/root_noopenat.go
+++ b/src/os/root_noopenat.go
@@ -158,6 +158,9 @@
if err := checkPathEscapes(r, name); err == errPathEscapes {
return &PathError{Op: "mkdirat", Path: name, Err: err}
}
+ if name == "" {
+ return &PathError{Op: "mkdirat", Path: name, Err: syscall.ENOENT}
+ }
prefix := r.root.name + string(PathSeparator)
if err := MkdirAll(prefix+name, perm); err != nil {
if pe, ok := err.(*PathError); ok {
diff --git a/src/os/root_openat.go b/src/os/root_openat.go
index d7c9334..92865e4 100644
--- a/src/os/root_openat.go
+++ b/src/os/root_openat.go
@@ -167,6 +167,12 @@
fi, e := r.Stat(fullname)
if e == nil && fi.Mode().IsDir() {
err = nil
+ } else if e == nil {
+ err = syscall.ENOTDIR
+ } else if !IsNotExist(e) {
+ // EPERM, ELOOP, etc.,
+ // probably more useful than EEXIST.
+ err = e
}
}
}
@@ -177,7 +183,12 @@
}
return struct{}{}, &PathError{Op: "mkdirat", Err: err}
}
- _, err := doInRoot(r, fullname, 0, openDirFunc, openLastComponentFunc)
+ flags := uint(doInRootCreatingDirectory)
+ switch runtime.GOOS {
+ case "linux", "windows":
+ flags = doInRootNoHandleTerminalSlash // see rootMkdir
+ }
+ _, err := doInRoot(r, fullname, flags, openDirFunc, openLastComponentFunc)
if err != nil {
if _, ok := err.(*PathError); !ok {
err = &PathError{Op: "mkdirat", Path: fullname, Err: err}
diff --git a/src/os/root_test.go b/src/os/root_test.go
index 5e0acf9..33a2f33 100644
--- a/src/os/root_test.go
+++ b/src/os/root_test.go
@@ -585,6 +585,11 @@
func TestRootMkdirAll(t *testing.T) {
for _, test := range rootTestCases {
+ if test.name == "directory does not exist" {
+ // Test expects error, mkdirall creates the missing directory.
+ // TestRootMultiMkdirAll covers this case better anyway, just skip.
+ continue
+ }
test.run(t, func(t *testing.T, target string, root *os.Root) {
wantError := test.wantError
if test.ltarget != "" {
@@ -593,7 +598,7 @@
wantError = true
}
- err := root.Mkdir(test.open, 0o777)
+ err := root.MkdirAll(test.open, 0o777)
if errEndsTest(t, err, wantError, "root.MkdirAll(%q)", test.open) {
return
}
@@ -3133,6 +3138,52 @@
})
}
+func TestRootMultiMkdirAllShallow(t *testing.T) {
+ runRootMultiTest(t, func(t *testing.T, test *rootMultiTest) (string, error) {
+ return testRootMultiMkdirAll(t, test, test.targetPath)
+ })
+}
+
+func TestRootMultiMkdirAllDeep(t *testing.T) {
+ runRootMultiTest(t, func(t *testing.T, test *rootMultiTest) (string, error) {
+ targetPath := test.targetPath
+ if len(targetPath) > 0 && os.IsPathSeparator(targetPath[len(targetPath)-1]) {
+ targetPath += "a/b/"
+ } else {
+ targetPath += "/a/b"
+ }
+ return testRootMultiMkdirAll(t, test, targetPath)
+ })
+}
+
+func testRootMultiMkdirAll(t *testing.T, test *rootMultiTest, targetPath string) (string, error) {
+ var mkdirAll = os.MkdirAll
+ if test.root != nil {
+ mkdirAll = test.root.MkdirAll
+ }
+
+ test.setOp("MkdirAll(%q, 0o777)", targetPath)
+ gotErr := mkdirAll(targetPath, 0o777)
+
+ switch {
+ case test.root != nil && test.target.lescapes():
+ // "mkdir ../target", or equivalent escaping path.
+ test.wantError(t, gotErr, os.ErrPathEscapes)
+ case test.root != nil && test.target.escapes():
+ // "mkdir ../target", or equivalent escaping path.
+ test.wantError(t, gotErr, errAny)
+ return "", errSkipRootConsistencyCheck
+ case test.root != nil && test.target.kind == testFileSymlink && test.target.target.kind == testFileAbsent && targetPath != test.targetPath:
+ // A minor inconsistency between Root.MkdirAll and os.MkdirAll:
+ // When an intermediate component of the tree being constructed is a
+ // dangling symlink, Root.MkdirAll will follow the symlink and create
+ // its target directory, while os.MkdirAll will fail with an error.
+ return "", errSkipRootConsistencyCheck
+ default:
+ }
+ return "", gotErr
+}
+
func TestRootMultiRename(t *testing.T) {
if runtime.GOOS == "wasip1" {
switch os.Getenv("GOWASIRUNTIME") {
+3 -5
View File
@@ -3,18 +3,16 @@ package go {
website = "https://go.dev"; website = "https://go.dev";
anitya = 1227; anitya = 1227;
version# = "1.26.5"; version# = "1.26.6";
source = remoteTar { source = remoteTar {
url = "https://go.dev/dl/go"+version+".src.tar.gz"; url = "https://go.dev/dl/go"+version+".src.tar.gz";
checksum = "13yt1u_NGOd62LO-WZ8W6CUXodOrEF5CdkiTTiH9E635IHn1luvlXYjsHpBXNFSw"; checksum = "BJQz9rGJ7ElMsZGURH7lw48Hw0x88RwdQJpINMomtgGCMK3AtwGCxDRkLE9REh5r";
compress = gzip; compress = gzip;
}; };
patches = [ patches = [
// https://go.dev/issue/77674 // https://go.dev/issue/77674
"746640.patch", "746640.patch",
// https://go.dev/issue/80308
"799064.patch",
]; ];
env = [ env = [
@@ -27,7 +25,7 @@ package go {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
mkdir /work/system/ "${TMPDIR}" mkdir /work/system/ "${TMPDIR}"
cp -r . /work/system/go cp -r . /work/system/go
+2 -2
View File
@@ -3,12 +3,12 @@ package googletest {
exclude = true; exclude = true;
anitya = 18290; anitya = 18290;
version# = "1.17.0"; version# = "1.18.0";
output = remoteGitHubRelease { output = remoteGitHubRelease {
suffix = "google/googletest"; suffix = "google/googletest";
tag = "v"+version; tag = "v"+version;
name = "googletest-"+version+".tar.gz"; name = "googletest-"+version+".tar.gz";
checksum = "-1r3ch8vPP8COF7xUH5hyX6bEJ4dN9TQh4IxrmpHr6vaig6mA3DdUpV4cihQ_9dw"; checksum = "ABVPC5sduQR7xfkZQm7UHSmBTaAJcVPRHS_lNMhlL99HU_YffpFmXbwRKeG1ZY8A";
compress = gzip; compress = gzip;
}; };
} }
@@ -2,11 +2,11 @@ package hakurei-source {
description = "hakurei source tree"; description = "hakurei source tree";
exclude = true; exclude = true;
version# = "0.4.5"; version# = "0.4.6";
output = remoteTar { output = remoteTar {
url = "https://git.gensokyo.uk/rosa/hakurei/archive/"+ url = "https://git.gensokyo.uk/rosa/hakurei/archive/"+
"v"+version+".tar.gz"; "v"+version+".tar.gz";
checksum = "5bvbuIRcDIrtijogwqXn3y8h5f3rVS4ZSVhOig6Galfzt3g-O3Ufb-tHL1kQCQWK"; checksum = "2HxvdykuSSymAu-c1WIwQAy3qT4dDm8B--93iL4uomBlBC8wfSWldbvPF1noNkUC";
compress = gzip; compress = gzip;
}; };
} }
@@ -27,16 +27,9 @@ package hakurei {
"CC=clang -O3 -Werror", "CC=clang -O3 -Werror",
]; ];
files = {
"hostname/main.go": "hostname";
};
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
echo 'Building test helper (hostname).'
go build -o /bin/hostname /usr/src/hostname/main.go
mkdir -p /work/system/libexec/hakurei/ mkdir -p /work/system/libexec/hakurei/
echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)." echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)."
@@ -71,7 +64,8 @@ mkdir -p /work/system/bin/
inputs = [ inputs = [
go, go,
pkg-config, pkgconf,
net-tools,
libseccomp, libseccomp,
acl, acl,
@@ -98,16 +92,9 @@ package hakurei-dist {
"CC=clang -O3 -Werror", "CC=clang -O3 -Werror",
]; ];
files = {
"hostname/main.go": "hostname";
};
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
echo 'Building test helper (hostname).'
go build -o /bin/hostname /usr/src/hostname/main.go
NAME=make`; NAME=make`;
check = ` check = `
NAME=all`; NAME=all`;
@@ -118,7 +105,8 @@ DESTDIR=/work "./${NAME}.sh"
inputs = [ inputs = [
go, go,
pkg-config, pkgconf,
net-tools,
libseccomp, libseccomp,
acl, acl,
@@ -146,7 +134,7 @@ package earlyinit {
]; ];
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
echo '# Building earlyinit.' echo '# Building earlyinit.'
go build -trimpath -v -o /work/ -ldflags="-s -w go build -trimpath -v -o /work/ -ldflags="-s -w
-11
View File
@@ -1,11 +0,0 @@
package main
import "os"
func main() {
if name, err := os.Hostname(); err != nil {
panic(err)
} else {
os.Stdout.WriteString(name)
}
}
+2 -2
View File
@@ -3,11 +3,11 @@ package harfbuzz {
website = "https://harfbuzz.github.io"; website = "https://harfbuzz.github.io";
anitya = 1299; anitya = 1299;
version# = "14.3.0"; version# = "14.3.1";
source = remoteGitHub { source = remoteGitHub {
suffix = "harfbuzz/harfbuzz"; suffix = "harfbuzz/harfbuzz";
tag = version; tag = version;
checksum = "C03eSJbyFvrOPXWhlHgwxfqUKyR9xQO_FKzbwQzT7hW9DTUAQIiwvUIf_6cqaKPm"; checksum = "ykVwQNNbvY38Y27VjAfk16SGcEO5NY5A8CFxJCJ8z0ARh5MdLImmONpy-ZSb79Il";
}; };
exec = meson { exec = meson {
+2 -2
View File
@@ -15,9 +15,9 @@ package hwdata {
exec = make { exec = make {
// awk: fatal: cannot open file `hwdata.spec' for reading: No such file or directory // awk: fatal: cannot open file `hwdata.spec' for reading: No such file or directory
inPlace = true; chdir = false;
// lspci: Unknown option 'A' (see "lspci --help") // lspci: Unknown option 'A' (see "lspci --help")
skipCheck = true; check = nil;
}; };
} }
+3 -3
View File
@@ -21,7 +21,7 @@ package iproute2 {
chmod = true; chmod = true;
exec = make { exec = make {
inPlace = true; chdir = false;
// drop default autoconf options // drop default autoconf options
configureName = "./configure"; configureName = "./configure";
configure = { configure = {
@@ -30,11 +30,11 @@ package iproute2 {
}; };
make = [ "CC=cc", "YACC=yacc" ]; make = [ "CC=cc", "YACC=yacc" ];
// wants root // wants root
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
pkg-config, pkgconf,
m4, m4,
byacc, byacc,
flex, flex,
+1 -1
View File
@@ -1,6 +1,6 @@
# #
# Automatically generated file; DO NOT EDIT. # Automatically generated file; DO NOT EDIT.
# Linux/x86 6.18.43 Kernel Configuration # Linux/x86 6.18.44 Kernel Configuration
# #
CONFIG_CC_VERSION_TEXT="clang version 22.1.8" CONFIG_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0 CONFIG_GCC_VERSION=0
+1 -1
View File
@@ -1,6 +1,6 @@
# #
# Automatically generated file; DO NOT EDIT. # Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.18.43 Kernel Configuration # Linux/arm64 6.18.44 Kernel Configuration
# #
CONFIG_CC_VERSION_TEXT="clang version 22.1.8" CONFIG_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0 CONFIG_GCC_VERSION=0
+13 -12
View File
@@ -3,11 +3,11 @@ package kernel-source {
website = "https://kernel.org"; website = "https://kernel.org";
exclude = true; exclude = true;
version# = "6.18.43"; version# = "6.18.44";
output = remoteTar { output = remoteTar {
url = "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+ url = "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
"snapshot/linux-"+version+".tar.gz"; "snapshot/linux-"+version+".tar.gz";
checksum = "SthN8PgD7oze4syBC54KJoky7JUpAmXJO0Y98an1ZJiqGppnf6N3kmZiZZdvi9dd"; checksum = "yNPGMl3A-EgU6LgD37PAcXIa9iUtP-AmoJuQozfGRSq6Eg1Eq4fdbpKy3iWewU9_";
compress = gzip; compress = gzip;
}; };
} }
@@ -25,8 +25,8 @@ package kernel-headers {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true; configure = nil;
make = [ make = [
"-f /usr/src/kernel-headers/Makefile", "-f /usr/src/kernel-headers/Makefile",
"O=/tmp/kbuild", "O=/tmp/kbuild",
@@ -35,7 +35,7 @@ package kernel-headers {
"INSTALL_HDR_PATH=/work/system", "INSTALL_HDR_PATH=/work/system",
"headers_install", "headers_install",
]; ];
skipCheck = true; check = nil;
install = ` install = `
cat \ cat \
/usr/src/version.h > \ /usr/src/version.h > \
@@ -46,9 +46,9 @@ cat \
checksum = arch { checksum = arch {
default = ""; default = "";
amd64 = "mZZqI0tEpqbr3sQKOFLBeNv-DC7pkHNqPI7JdSSmo40sFCF2XnAMcah1DcUK2HTe"; amd64 = "vN5Ts9yAlHTntcQcNGJSisY5guYsYfvGnQqI1NzTBzvhBMPD432WB3B0KFGYQntA";
arm64 = "e6cD6TsBr1e-zONKtocvbRwmSnxqC_2K7A2KvMcO6lnpt4MXL1gsyx6k-BXqC19Z"; arm64 = "FQtpqCA0tlz17RJP8a5t9YEM_6F9kGPqQ9Z60gFrkVP3v8_P-Vnf5S7wLlxyRlOe";
riscv64 = "cljgtOrTCpyXoQLaKVmnnWPbCWkoXuMIVNjc6YXsy-zgsFzRA-H8yfJ1NojS867z"; riscv64 = "U5yQ9TI5_7diyrCcm2Iqh3XCMl0P60oQGeDMWxt3OQ91zFWPQ5FCH-eoYG9tSTMT";
}; };
inputs = [ rsync ]; inputs = [ rsync ];
} }
@@ -86,11 +86,12 @@ install -Dm0500 \
exclusive = true; exclusive = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true;
configure = nil;
// Build, install, and boot kernel before running kselftest on it. // Build, install, and boot kernel before running kselftest on it.
skipCheck = true; check = nil;
make = [ make = [
"-f /usr/src/kernel/Makefile", "-f /usr/src/kernel/Makefile",
@@ -154,7 +155,7 @@ package gen_init_cpio {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
mkdir -p /work/system/bin/ mkdir -p /work/system/bin/
cc -o /work/system/bin/gen_init_cpio usr/gen_init_cpio.c cc -o /work/system/bin/gen_init_cpio usr/gen_init_cpio.c
+1 -1
View File
@@ -1,6 +1,6 @@
# #
# Automatically generated file; DO NOT EDIT. # Automatically generated file; DO NOT EDIT.
# Linux/riscv 6.18.43 Kernel Configuration # Linux/riscv 6.18.44 Kernel Configuration
# #
CONFIG_CC_VERSION_TEXT="clang version 22.1.8" CONFIG_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0 CONFIG_GCC_VERSION=0
+2 -2
View File
@@ -1,5 +1,5 @@
#define LINUX_VERSION_CODE 397866 #define LINUX_VERSION_CODE 397868
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c))) #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#define LINUX_VERSION_MAJOR 6 #define LINUX_VERSION_MAJOR 6
#define LINUX_VERSION_PATCHLEVEL 18 #define LINUX_VERSION_PATCHLEVEL 18
#define LINUX_VERSION_SUBLEVEL 42 #define LINUX_VERSION_SUBLEVEL 44
+1 -1
View File
@@ -22,7 +22,7 @@ package kmod {
}; };
// makes assumptions about the running kernel // makes assumptions about the running kernel
skipTest = true; test = false;
}; };
inputs = [ inputs = [
+2 -2
View File
@@ -18,8 +18,8 @@ package libaio {
env = [ "PATH=/system/sbin" ]; env = [ "PATH=/system/sbin" ];
bin = [ "bash" ]; bin = [ "bash" ];
exec = make { exec = make {
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
preCheck = "rm harness/cases/20.t; "+ // flaky preCheck = "rm harness/cases/20.t; "+ // flaky
"CFLAGS='"+ "CFLAGS='"+
"-Wno-unknown-warning-option "+ "-Wno-unknown-warning-option "+
+3 -3
View File
@@ -16,9 +16,9 @@ package libbpf {
chmod = true; chmod = true;
exec = make { exec = make {
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
skipCheck = true; check = nil;
install = "make DESTDIR=/work LIBSUBDIR=lib install"; install = "make DESTDIR=/work LIBSUBDIR=lib install";
}; };
+4 -12
View File
@@ -23,18 +23,10 @@ package libcap {
bin = [ "bash" ]; bin = [ "bash" ];
exec = make { exec = make {
skipConfigure = true; chdir = false;
inPlace = true; configure = nil;
make = [ "CC=cc", "all" ];
make = [ check = [ "CC=cc", "test" ];
"CC=cc",
"all",
];
check = [
"CC=cc",
"test",
];
}; };
inputs = [ inputs = [
+2 -2
View File
@@ -3,7 +3,7 @@ package libexpat {
website = "https://libexpat.github.io"; website = "https://libexpat.github.io";
anitya = 770; anitya = 770;
version# = "2.8.2"; version# = "2.8.3";
source = remoteGitHubRelease { source = remoteGitHubRelease {
suffix = "libexpat/libexpat"; suffix = "libexpat/libexpat";
tag = "R_"+replace { tag = "R_"+replace {
@@ -12,7 +12,7 @@ package libexpat {
new = "_"; new = "_";
}; };
name = "expat-"+version+".tar.bz2"; name = "expat-"+version+".tar.bz2";
checksum = "98Pdyj5QtO7QRtNFXTWsCNCixQDx701ZGql2B-JIrTDkw49J5WXXUwnS4AdMlM4L"; checksum = "prHQc14YY3Gp6BfflneNcVyRXM-AxFCqiigxrGL9TT1sGhVODvI_9JNR2xnZlZSj";
compress = bzip2; compress = bzip2;
}; };
+3 -3
View File
@@ -3,12 +3,12 @@ package libpsl {
website = "https://rockdaboot.github.io/libpsl"; website = "https://rockdaboot.github.io/libpsl";
anitya = 7305; anitya = 7305;
version# = "0.23.1"; version# = "0.23.2";
source = remoteGitHubRelease { source = remoteGitHubRelease {
suffix = "rockdaboot/libpsl"; suffix = "rockdaboot/libpsl";
tag = version; tag = version;
name = "libpsl-"+version+".tar.gz"; name = "libpsl-"+version+".tar.gz";
checksum = "9wu0JxiNGfY3TuYeCmOq9Xm3faPHole5is_3ZL2KUCh8FyaYwpl7a85SNsz8FmPz"; checksum = "-XIKaQK0QoyzXpwezyvGzDdIBCUTqPyd8jU6axIusrnma-qsYxhLUO1Oycwcelr2";
compress = gzip; compress = gzip;
}; };
@@ -22,7 +22,7 @@ test_disable 'int main(){return 0;}' tests/test-is-public-builtin.c
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
python, python,
]; ];
} }
+2 -2
View File
@@ -20,7 +20,7 @@ package libtirpc {
exec = make { exec = make {
generate = "sh -e ./bootstrap"; generate = "sh -e ./bootstrap";
configure = { configure = {
"CFLAGS": `"$(pkg-config --cflags libbsd-overlay) ${CFLAGS:-}"`; "CFLAGS": `"$(pkgconf --cflags libbsd-overlay) ${CFLAGS:-}"`;
"disable-gssapi"; "disable-gssapi";
}; };
}; };
@@ -28,7 +28,7 @@ package libtirpc {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
libbsd, libbsd,
kernel-headers, kernel-headers,
+4 -6
View File
@@ -16,13 +16,11 @@ package libucontext {
enterSource = true; enterSource = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true; chdir = false;
inPlace = true;
make = [ configure = nil;
"ARCH=" + linuxArch, make = [ "ARCH=" + linuxArch ];
];
install = "make prefix=/system DESTDIR=/work install"; install = "make prefix=/system DESTDIR=/work install";
}; };
} }
+2 -2
View File
@@ -15,14 +15,14 @@ package libxslt {
generate = "NOCONFIGURE=1 ./autogen.sh"; generate = "NOCONFIGURE=1 ./autogen.sh";
// python libxml2 cyclic dependency // python libxml2 cyclic dependency
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
automake, automake,
libtool, libtool,
python, python,
pkg-config, pkgconf,
libxml2, libxml2,
]; ];
+1 -1
View File
@@ -7,7 +7,7 @@ package lit {
exec = pip { exec = pip {
append = [ "llvm", "utils", "lit" ]; append = [ "llvm", "utils", "lit" ];
// already checked during llvm // already checked during llvm
skipCheck = true; check = nil;
}; };
inputs = [ python-setuptools ]; inputs = [ python-setuptools ];
+2 -2
View File
@@ -56,7 +56,7 @@ message(NOTICE "${LLVM_VERSION_MAJOR}")
"COMPILER_RT_BUILD_PROFILE": "OFF"; "COMPILER_RT_BUILD_PROFILE": "OFF";
"COMPILER_RT_BUILD_XRAY": "OFF"; "COMPILER_RT_BUILD_XRAY": "OFF";
}; };
skipTest = true; test = nil;
postInstall = ` postInstall = `
mkdir -p "/work/system/lib/clang/$LLVM_VERSION_MAJOR/lib/" mkdir -p "/work/system/lib/clang/$LLVM_VERSION_MAJOR/lib/"
ln -s \ ln -s \
@@ -119,7 +119,7 @@ package early-runtimes {
"LLVM_ENABLE_ZSTD": "FORCE_ON"; "LLVM_ENABLE_ZSTD": "FORCE_ON";
"LLVM_ENABLE_LIBXML2": "OFF"; "LLVM_ENABLE_LIBXML2": "OFF";
}; };
skipTest = true; test = nil;
}; };
inputs = [ inputs = [
+4 -14
View File
@@ -17,20 +17,10 @@ package lm_sensors {
bin = [ "perl" ]; bin = [ "perl" ];
populateUsrBin = true; populateUsrBin = true;
exec = make { exec = make {
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
make = [ "CC=cc", "ETCDIR=/system/etc", "PREFIX=/system" ];
make = [ check = [ "CC=cc", "check" ];
"CC=cc",
"ETCDIR=/system/etc",
"PREFIX=/system",
];
check = [
"CC=cc",
"check",
];
install = "make DESTDIR=/work PREFIX=/system install"; install = "make DESTDIR=/work PREFIX=/system install";
}; };
+2 -2
View File
@@ -20,8 +20,8 @@ package lua {
chmod = true; chmod = true;
exec = make { exec = make {
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
make = [ "CC='clang -fPIC'", "all" ]; make = [ "CC='clang -fPIC'", "all" ];
check = [ "test" ]; check = [ "test" ];
install = ` install = `
+2 -2
View File
@@ -16,11 +16,11 @@ package lvm2 {
exec = make { exec = make {
// requires root // requires root
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
pkg-config, pkgconf,
libaio, libaio,
kernel-headers, kernel-headers,
+2 -2
View File
@@ -3,11 +3,11 @@ package meson {
website = "https://mesonbuild.com"; website = "https://mesonbuild.com";
anitya = 6472; anitya = 6472;
version# = "1.11.2"; version# = "1.12.0";
source = remoteGitHub { source = remoteGitHub {
suffix = "mesonbuild/meson"; suffix = "mesonbuild/meson";
tag = version; tag = version;
checksum = "9AMilGxTOVqPA2DaGMASyuVs1BeTzgDZ0NH2oSYoRZk846ApvfOBa4cc18XEEK7M"; checksum = "K0hm0h26_6e3-1poYZKwj18IB6bdAtYE-whpROtTCSpVN5GllwSwbXC2xPYcSFAJ";
}; };
patches = [ patches = [
"respect-colour.patch", "respect-colour.patch",
+1 -1
View File
@@ -21,6 +21,6 @@ package musl-fts {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
]; ];
} }
+1 -1
View File
@@ -21,6 +21,6 @@ package musl-obstack {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
]; ];
} }
+5 -11
View File
@@ -23,14 +23,9 @@ package musl-headers {
]; ];
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipCheck = true; make = [ "DESTDIR=/work", "install-headers" ];
check = nil;
make = [
"DESTDIR=/work",
"install-headers",
];
install = "# headers installed during make"; install = "# headers installed during make";
}; };
@@ -53,9 +48,8 @@ package musl {
]; ];
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipCheck = true; check = nil;
postInstall = ` postInstall = `
mkdir -p /work/system/bin mkdir -p /work/system/bin
COMPAT_LINKER_NAME="ld-musl-` + linuxArch + `.so.1" COMPAT_LINKER_NAME="ld-musl-` + linuxArch + `.so.1"
+1 -1
View File
@@ -19,7 +19,7 @@ package ncurses {
}; };
// "tests" are actual demo programs, not a test suite. // "tests" are actual demo programs, not a test suite.
skipCheck = true; check = nil;
postInstall = ` postInstall = `
find /work/system/lib \ find /work/system/lib \
@@ -0,0 +1,115 @@
From 7a8f42fb20013a1493d8cae1c43436f85e656f2d Mon Sep 17 00:00:00 2001
From: Zephkeks <zephyrofficialdiscord@gmail.com>
Date: Tue, 13 May 2025 11:04:17 +0200
Subject: [PATCH] CVE-2025-46836: interface.c: Stack-based Buffer Overflow in
get_name()
Coordinated as GHSA-pfwf-h6m3-63wf
---
lib/interface.c | 63 ++++++++++++++++++++++++++++++-------------------
1 file changed, 39 insertions(+), 24 deletions(-)
diff --git a/lib/interface.c b/lib/interface.c
index 71d4163..a054f12 100644
--- a/lib/interface.c
+++ b/lib/interface.c
@@ -211,32 +211,47 @@ static int if_readconf(void)
}
static const char *get_name(char *name, const char *p)
+/* Safe version — guarantees at most IFNAMSIZ1 bytes are copied
+ and the destination buffer is always NULterminated. */
{
- while (isspace(*p))
- p++;
- while (*p) {
- if (isspace(*p))
- break;
- if (*p == ':') { /* could be an alias */
- const char *dot = p++;
- while (*p && isdigit(*p)) p++;
- if (*p == ':') {
- /* Yes it is, backup and copy it. */
- p = dot;
- *name++ = *p++;
- while (*p && isdigit(*p)) {
- *name++ = *p++;
- }
- } else {
- /* No, it isn't */
- p = dot;
- }
- p++;
- break;
- }
- *name++ = *p++;
+ char *dst = name; /* current write ptr */
+ const char *end = name + IFNAMSIZ - 1; /* last byte we may write */
+
+ /* Skip leading whitespace. */
+ while (isspace((unsigned char)*p))
+ ++p;
+
+ /* Copy until whitespace, end of string, or buffer full. */
+ while (*p && !isspace((unsigned char)*p) && dst < end) {
+ if (*p == ':') { /* possible alias veth0:123: */
+ const char *dot = p; /* remember the colon */
+ ++p;
+ while (*p && isdigit((unsigned char)*p))
+ ++p;
+
+ if (*p == ':') { /* confirmed alias */
+ p = dot; /* rewind and copy it all */
+
+ /* copy the colon */
+ if (dst < end)
+ *dst++ = *p++;
+
+ /* copy the digits */
+ while (*p && isdigit((unsigned char)*p) && dst < end)
+ *dst++ = *p++;
+
+ if (*p == ':') /* consume trailing colon */
+ ++p;
+ } else { /* if so treat as normal */
+ p = dot;
+ }
+ break; /* interface name ends here */
+ }
+
+ *dst++ = *p++; /* ordinary character copy */
}
- *name++ = '\0';
+
+ *dst = '\0'; /* always NULterminate */
return p;
}
From ddb0e375fb9ca95bb69335540b85bbdaa2714348 Mon Sep 17 00:00:00 2001
From: Bernd Eckenfels <net-tools@lina.inka.de>
Date: Sat, 17 May 2025 21:53:23 +0200
Subject: [PATCH] Interface statistic regression after 7a8f42fb2
---
lib/interface.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/interface.c b/lib/interface.c
index a054f12..ca4adf1 100644
--- a/lib/interface.c
+++ b/lib/interface.c
@@ -239,12 +239,11 @@ static const char *get_name(char *name, const char *p)
/* copy the digits */
while (*p && isdigit((unsigned char)*p) && dst < end)
*dst++ = *p++;
-
- if (*p == ':') /* consume trailing colon */
- ++p;
} else { /* if so treat as normal */
p = dot;
}
+ if (*p == ':') /* consume trailing colon */
+ ++p;
break; /* interface name ends here */
}
@@ -0,0 +1,53 @@
From a7926399a04ee8e629a02a2aeb6de1952d42d559 Mon Sep 17 00:00:00 2001
From: Bernd Eckenfels <net-tools@lina.inka.de>
Date: Sat, 17 May 2025 21:11:07 +0200
Subject: [PATCH] ipmaddr.c: Stack-based buffer Overflow in parse_hex()
Coordinated as GHSA-h667-qrp8-gj58.
---
ipmaddr.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ipmaddr.c b/ipmaddr.c
index 64b7564..623fadd 100644
--- a/ipmaddr.c
+++ b/ipmaddr.c
@@ -91,17 +91,17 @@ static int parse_lla(char *str, char *addr)
return len;
}
-static int parse_hex(char *str, unsigned char *addr)
+static int parse_hex(char *str, unsigned char *dst, size_t dstlen)
{
int len=0;
- while (*str) {
+ while (len < dstlen && *str) {
int tmp;
if (str[1] == 0)
return -1;
if (sscanf(str, "%02x", &tmp) != 1)
return -1;
- addr[len] = tmp;
+ dst[len] = tmp;
len++;
str += 2;
}
@@ -152,7 +152,7 @@ void read_dev_mcast(struct ma_info **result_p)
m.addr.family = AF_PACKET;
- len = parse_hex(hexa, (unsigned char*)&m.addr.data);
+ len = parse_hex(hexa, (unsigned char*)&m.addr.data, sizeof(m.addr.data));
if (len >= 0) {
struct ma_info *ma = xmalloc(sizeof(m));
memcpy(ma, &m, sizeof(m));
@@ -222,7 +222,7 @@ void read_igmp6(struct ma_info **result_p)
m.addr.family = AF_INET6;
- len = parse_hex(hexa, (unsigned char*)&m.addr.data);
+ len = parse_hex(hexa, (unsigned char*)&m.addr.data, sizeof(m.addr.data));
if (len >= 0) {
struct ma_info *ma = xmalloc(sizeof(m));
memcpy(ma, &m, sizeof(m));
@@ -0,0 +1,71 @@
From 84041080a5d4794045b098ced90e0309bcbcff44 Mon Sep 17 00:00:00 2001
From: Zephkeks <zephyrofficialdiscord@gmail.com>
Date: Sat, 17 May 2025 22:11:37 +0200
Subject: [PATCH] proc.c: Stack-based Buffer Overflow in net-tools
(proc_gen_fmt)
Coordinated as GHSA-w7jq-cmw2-cq59.
---
lib/proc.c | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/lib/proc.c b/lib/proc.c
index d51d09f..02aae49 100644
--- a/lib/proc.c
+++ b/lib/proc.c
@@ -17,6 +17,8 @@ char *proc_gen_fmt(const char *name, int more, FILE * fh,...)
char buf[512], format[512] = "";
char *title, *head, *hdr;
va_list ap;
+ size_t format_len = 0;
+ size_t format_size = sizeof(format);
if (!fgets(buf, (sizeof buf) - 1, fh))
return NULL;
@@ -33,14 +35,43 @@ char *proc_gen_fmt(const char *name, int more, FILE * fh,...)
*hdr++ = 0;
if (!strcmp(title, head)) {
- strcat(format, va_arg(ap, char *));
+ const char *arg = va_arg(ap, char *);
+ size_t arg_len = strlen(arg);
+
+ /* Check if we have enough space for format specifier + space */
+ if (format_len + arg_len + 1 >= format_size) {
+ fprintf(stderr, "warning: format buffer overflow in %s\n", name);
+ va_end(ap);
+ return NULL;
+ }
+
+ strcpy(format + format_len, arg);
+ format_len += arg_len;
+
title = va_arg(ap, char *);
if (!title)
break;
} else {
- strcat(format, "%*s"); /* XXX */
+ /* Check if we have enough space for "%*s" */
+ if (format_len + 3 >= format_size) {
+ fprintf(stderr, "warning: format buffer overflow in %s\n", name);
+ va_end(ap);
+ return NULL;
+ }
+
+ strcpy(format + format_len, "%*s");
+ format_len += 3;
}
- strcat(format, " ");
+
+ /* Check if we have space for the trailing space */
+ if (format_len + 1 >= format_size) {
+ fprintf(stderr, "warning: format buffer overflow in %s\n", name);
+ va_end(ap);
+ return NULL;
+ }
+
+ format[format_len++] = ' ';
+ format[format_len] = '\0';
}
va_end(ap);
@@ -0,0 +1,22 @@
From f84cd22a921c25c56a6c194d4825dbd9ceea0e5f Mon Sep 17 00:00:00 2001
From: Bernd <bernd@eckenfels.net>
Date: Sat, 22 Mar 2025 00:17:10 +0100
Subject: [PATCH] Update proc.c; remove redundant null check (CodeQL #3) (#44)
---
lib/proc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/proc.c b/lib/proc.c
index ce85fd1..d51d09f 100644
--- a/lib/proc.c
+++ b/lib/proc.c
@@ -35,7 +35,7 @@ char *proc_gen_fmt(const char *name, int more, FILE * fh,...)
if (!strcmp(title, head)) {
strcat(format, va_arg(ap, char *));
title = va_arg(ap, char *);
- if (!title || !head)
+ if (!title)
break;
} else {
strcat(format, "%*s"); /* XXX */
@@ -0,0 +1,33 @@
package net-tools {
description = "the collection of base networking utilities for Linux";
anitya = 10231;
version# = "2.10";
source = remoteTar {
url = "https://downloads.sourceforge.net/project/net-tools/"+
"net-tools-"+version+".tar.xz";
compress = xz;
checksum = "YLmSUeHOYnhYhjvnisX6MQNkPJRzOIgSZBHRiWmBdzzziWYJVY6hOpM8eWnAZ11N";
};
patches = [
"CVE-2025-46836.patch",
"GHSA-h667-qrp8-gj58.patch",
"f84cd22a921c25c56a6c194d4825dbd9ceea0e5f.patch",
"GHSA-w7jq-cmw2-cq59.patch",
];
enterSource = true;
writable = true;
exec = make {
chdir = false;
configureName = "(set +o pipefail && yes '' | make config)";
check = nil;
};
inputs = [
bash,
kernel-headers,
];
}
+2 -2
View File
@@ -50,7 +50,7 @@ package libnftnl {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
libmnl, libmnl,
kernel-headers, kernel-headers,
@@ -95,7 +95,7 @@ chmod +w /etc/ && ln -s ../usr/src/iptables/etc/ethertypes /etc/
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
bash, bash,
python, python,
+1 -1
View File
@@ -12,7 +12,7 @@ package noto {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
install = ` install = `
DEST=/work/system/share/fonts/noto DEST=/work/system/share/fonts/noto
for font in $(ls -d fonts/*/); do for font in $(ls -d fonts/*/); do
+7 -8
View File
@@ -17,7 +17,7 @@ package nss {
website = "https://firefox-source-docs.mozilla.org/security/nss/index.html"; website = "https://firefox-source-docs.mozilla.org/security/nss/index.html";
anitya = 2503; anitya = 2503;
version# = "3.126"; version# = "3.126.1";
source = remoteGitHub { source = remoteGitHub {
suffix = "nss-dev/nss"; suffix = "nss-dev/nss";
tag = "NSS_"+join { tag = "NSS_"+join {
@@ -28,7 +28,7 @@ package nss {
}; };
sep = "_"; sep = "_";
}+"_RTM"; }+"_RTM";
checksum = "gzMK4RkCHhgmhe33imV0qzZ8e2_VFAsF5M2db-1jrCWzh6XGijm51P2DIdDO2Dsf"; checksum = "3J7o7P3KlE8Cen4fzHLwvDKA1rrcJ84yBTniJHcIBw59LPT-7Q0NxL2CC4BKGW3F";
}; };
extra = [ nspr ]; extra = [ nspr ];
@@ -38,10 +38,9 @@ package nss {
early = "\nln -s extra/nspr/nspr /usr/src/nspr\nchmod +w ../nspr/\n"; early = "\nln -s extra/nspr/nspr /usr/src/nspr\nchmod +w ../nspr/\n";
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true; chdir = false;
inPlace = true; configure = nil;
make = [ make = [
"CCC=clang++", "CCC=clang++",
"NSDISTMODE=copy", "NSDISTMODE=copy",
@@ -49,7 +48,7 @@ package nss {
"USE_64=1", "USE_64=1",
"nss_build_all", "nss_build_all",
]; ];
skipCheck = true; check = nil;
install = ` install = `
cp -r \ cp -r \
/usr/src/dist/. \ /usr/src/dist/. \
@@ -80,7 +79,7 @@ package nss-cacert {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
mkdir -p /work/system/etc/ssl/{certs/unbundled,certs/hashed,trust-source} mkdir -p /work/system/etc/ssl/{certs/unbundled,certs/hashed,trust-source}
buildcatrust \ buildcatrust \
+1 -1
View File
@@ -21,7 +21,7 @@ package openssl {
]; ];
exec = make { exec = make {
omitDefaults = true; defaults = false;
configureName = "/usr/src/openssl/Configure"; configureName = "/usr/src/openssl/Configure";
configure = { configure = {
+1 -1
View File
@@ -18,7 +18,7 @@ package pango {
"cairo": "enabled"; "cairo": "enabled";
}; };
// Fontconfig error: Cannot load default config file: File not found: /etc/fonts/fonts.conf // Fontconfig error: Cannot load default config file: File not found: /etc/fonts/fonts.conf
skipTest = true; test = false;
}; };
inputs = [ inputs = [
+3 -3
View File
@@ -28,8 +28,8 @@ disable_test ext/POSIX/t/time.t
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
inPlace = true; chdir = false;
configureName = "./Configure"; configureName = "./Configure";
configure = { configure = {
@@ -70,7 +70,7 @@ package perl-Module-Build {
chmod = true; chmod = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
perl Build.PL --prefix=/system perl Build.PL --prefix=/system
./Build build`; ./Build build`;
+16
View File
@@ -0,0 +1,16 @@
package pkgconf {
description = "package compiler and linker metadata toolkit";
website = "https://github.com/pkgconf/pkgconf";
anitya = 12753;
version# = "3.0.5";
source = remoteGitHub {
suffix = "pkgconf/pkgconf";
tag = "pkgconf-"+version;
checksum = "ZWak6fggXCzZkROSnSrl9twRRV9OJA7Q4DamFKEm094e2vgf_99gCxkmrZP3VFYH";
};
exec = meson {
postInstall = "ln -s pkgconf /work/system/bin/pkg-config";
};
}
+3 -3
View File
@@ -3,12 +3,12 @@ package procps {
website = "https://gitlab.com/procps-ng/procps"; website = "https://gitlab.com/procps-ng/procps";
anitya = 3708; anitya = 3708;
version# = "4.0.6"; version# = "4.0.7";
source = remoteGitLab { source = remoteGitLab {
domain = "gitlab.com"; domain = "gitlab.com";
suffix = "procps-ng/procps"; suffix = "procps-ng/procps";
ref = "v"+version; ref = "v"+version;
checksum = "pl_fZLvDlv6iZTkm8l_tHFpzTDVFGCiSJEs3eu0zAX6u36AV36P_En8K7JPScRWM"; checksum = "h5d0Wd_YyDzeRyduE4YawF0edvyMWA3UBcAXWAMg2fdtHhl5i1r0QeDu1-xAyR8g";
}; };
exec = make { exec = make {
@@ -24,6 +24,6 @@ package procps {
libtool, libtool,
gzip, gzip,
pkg-config, pkgconf,
]; ];
} }
+61 -18
View File
@@ -3,6 +3,9 @@ package python {
website = "https://www.python.org"; website = "https://www.python.org";
anitya = 13254; anitya = 13254;
// too many inputs; early variant available
bootstrap = false;
version# = "3.14.7"; version# = "3.14.7";
source = remoteTar { source = remoteTar {
url = "https://www.python.org/ftp/python/"+version+ url = "https://www.python.org/ftp/python/"+version+
@@ -148,18 +151,18 @@ package python-setuptools {
website = "https://pypi.org/project/setuptools"; website = "https://pypi.org/project/setuptools";
anitya = 4021; anitya = 4021;
version# = "83.0.0"; version# = "84.0.0";
source = remoteGitHub { source = remoteGitHub {
suffix = "pypa/setuptools"; suffix = "pypa/setuptools";
tag = "v"+version; tag = "v"+version;
checksum = "WqYSqCAvwpcIG6yXV8vVzRMNWl2CrcPOUPwlYrLV70ykHSpKxW1-XYQ4Z4n0ebAt"; checksum = "K9PGFv7ju_v4sykQCcROCc8Zdz3TfxYv95JlKFGXUnpf1yqRZW3oA0LuUQfE2x8n";
}; };
exec = pip { exec = pip {
// error: invalid command 'dist_info' // error: invalid command 'dist_info'
buildIsolation = true; buildIsolation = true;
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
runtime = [ python ]; runtime = [ python ];
@@ -170,11 +173,11 @@ package python-wheel {
website = "https://peps.python.org/pep-0427"; website = "https://peps.python.org/pep-0427";
anitya = 11428; anitya = 11428;
version# = "0.47.0"; version# = "0.48.0";
source = remoteGitHub { source = remoteGitHub {
suffix = "pypa/wheel"; suffix = "pypa/wheel";
tag = version; tag = version;
checksum = "HZ-MvkUP8mbbx2YmsRNswj_bbOCIiXckuHqL5Qbvb5NxN5DYfWnqwkGNyS7OrId0"; checksum = "h-UZQHS-NwB3b9YxYpJePR5cbDGZaKxz4bdhYjilWdQXAE46SV7A1CwZKzZcuZFh";
}; };
exec = pip { exec = pip {
@@ -209,7 +212,7 @@ package python-vcs-versioning {
// upstream is monorepo of two packages (setuptools-scm) // upstream is monorepo of two packages (setuptools-scm)
append = [ "vcs-versioning" ]; append = [ "vcs-versioning" ];
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
@@ -243,7 +246,7 @@ package python-setuptools-scm {
// upstream is monorepo of two packages // upstream is monorepo of two packages
append = [ "setuptools-scm" ]; append = [ "setuptools-scm" ];
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
@@ -273,7 +276,7 @@ package python-flit-core {
// upstream has other unused packages with many dependencies // upstream has other unused packages with many dependencies
append = [ "flit_core" ]; append = [ "flit_core" ];
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
runtime = [ python ]; runtime = [ python ];
@@ -293,7 +296,7 @@ package python-packaging {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-flit-core ]; inputs = [ python-flit-core ];
@@ -314,7 +317,7 @@ package python-pathspec {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-flit-core ]; inputs = [ python-flit-core ];
@@ -335,7 +338,7 @@ package python-trove-classifiers {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-setuptools ]; inputs = [ python-setuptools ];
@@ -360,30 +363,68 @@ package python-pluggy {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-setuptools-scm ]; inputs = [ python-setuptools-scm ];
runtime = [ python ]; runtime = [ python ];
} }
package python-poetry-core {
description = "poetry PEP 517 Build Backend & Core Utilities";
website = "https://github.com/python-poetry/poetry-core";
anitya = 71155;
version# = "2.4.1";
source = remoteGitHub {
suffix = "python-poetry/poetry-core";
tag = version;
checksum = "tf9OeSUv9TJwKd48fQIU2uGtZ36GN-PDmPDZzjClozzLjv-rQ5nIbOg9gOXpegiH";
};
exec = pip {
// pytest circular dependency
check = nil;
};
}
package python-tomlkit {
description = "style-preserving TOML library for Python";
website = "https://github.com/python-poetry/tomlkit";
anitya = 19609;
version# = "0.15.1";
source = remoteGitHub {
suffix = "python-poetry/tomlkit";
tag = version;
checksum = "6n8h0Yf-OO0ARildxqyB1mB1EhS7uALtqFJqD7t7G1JSFTTb9RGRWSpCg-vamuu8";
};
exec = pip {
// pytest circular dependency
check = nil;
};
inputs = [ python-poetry-core ];
}
package python-hatchling { package python-hatchling {
description = "the extensible, standards compliant build backend used by Hatch"; description = "the extensible, standards compliant build backend used by Hatch";
website = "https://hatch.pypa.io"; website = "https://hatch.pypa.io";
anitya = 16137; anitya = 16137;
version# = "1.17.1"; version# = "1.18.0";
source = remoteGitHub { source = remoteGitHub {
suffix = "pypa/hatch"; suffix = "pypa/hatch";
tag = "hatch-v"+version; tag = "hatch-v"+version;
checksum = "FK9PkGIkL3wyVFHOKrx9lSRqoevuQ_TFrN-pMqsoFKsh5eim4pfzx7MvL3ioif9o"; checksum = "a_ntndxBlMdqSVW3PkiAY42m-NDgyWJcKLWFIVTB_5PciVeJdYYdbcdF6jsd0U96";
}; };
exec = pip { exec = pip {
// upstream has other unused packages with many dependencies // upstream has other unused packages with many dependencies
append = [ "backend" ]; append = [ "backend" ];
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
@@ -391,6 +432,7 @@ package python-hatchling {
python-pathspec, python-pathspec,
python-trove-classifiers, python-trove-classifiers,
python-pluggy, python-pluggy,
python-tomlkit,
]; ];
runtime = [ runtime = [
@@ -398,6 +440,7 @@ package python-hatchling {
python-pathspec, python-pathspec,
python-trove-classifiers, python-trove-classifiers,
python-pluggy, python-pluggy,
python-tomlkit,
]; ];
} }
@@ -415,7 +458,7 @@ package python-pygments {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-hatchling ]; inputs = [ python-hatchling ];
@@ -440,7 +483,7 @@ package python-iniconfig {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-setuptools-scm ]; inputs = [ python-setuptools-scm ];
@@ -465,7 +508,7 @@ package python-pytest {
exec = pip { exec = pip {
// many dependencies // many dependencies
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
@@ -0,0 +1,12 @@
diff --git a/tests/qemu-iotests/tests/copy-before-write b/tests/qemu-iotests/tests/copy-before-write
index 236cb8ac37..0eac14005e 100755
--- a/tests/qemu-iotests/tests/copy-before-write
+++ b/tests/qemu-iotests/tests/copy-before-write
@@ -279,6 +279,7 @@ read 1048576/1048576 bytes at offset 0
return log
def test_timeout_break_guest(self):
+ return
log = self.do_cbw_timeout('break-guest-write')
# macOS and FreeBSD tend to represent ETIMEDOUT as
# "Operation timed out", when Linux prefer
@@ -0,0 +1,16 @@
diff --git a/tests/qemu-iotests/150 b/tests/qemu-iotests/150
index fab0faa389..d71fb5978d 100755
--- a/tests/qemu-iotests/150
+++ b/tests/qemu-iotests/150
@@ -41,6 +41,11 @@ _supported_fmt raw qcow2
_supported_proto file
_supported_os Linux
+# work directory is never an overlay
+if [ "$(stat -fc '%T' /work/)" = "zfs" ]; then
+ _notrun 'fails on zfs'
+fi
+
img_size=1048576
@@ -0,0 +1,13 @@
diff --git a/configure b/configure
index 6ddfe4b534..1cba33d562 100755
--- a/configure
+++ b/configure
@@ -1946,7 +1946,7 @@ if test "$skip_meson" = no; then
test -n "$gdb_bin" && meson_option_add "-Dgdb=$gdb_bin"
run_meson() {
- NINJA=$ninja $meson setup "$@" "$PWD" "$source_path"
+ NINJA=$ninja CLICOLOR_FORCE=1 $meson setup "$@" "$PWD" "$source_path"
}
eval run_meson $meson_options
if test "$?" -ne 0 ; then
+11 -8
View File
@@ -3,16 +3,22 @@ package qemu {
website = "https://www.qemu.org"; website = "https://www.qemu.org";
anitya = 13607; anitya = 13607;
version# = "11.0.3"; version# = "11.1.0";
source = remoteTar { source = remoteTar {
url = "https://download.qemu.org/qemu-"+version+".tar.bz2"; url = "https://download.qemu.org/qemu-"+version+".tar.bz2";
checksum = "cY1nZe92-WGeOErkkEXU0pDidJxBFgF4JCtUv1IJk0qVUYHw3VSZfVms1NqWfTLq"; checksum = "nOjPiAFhPGVBnM2rYokJhMDUhFM_6ec-B2N-1-LB1wmCiLzF5_ppqSgkNESuoBFu";
compress = bzip2; compress = bzip2;
}; };
patches = [ patches = [
"meson-colour.patch",
"iotests-zfs.patch",
"disable-mcast-test.patch", "disable-mcast-test.patch",
// fails with ipv6 disabled // fails with ipv6 disabled
"disable-netdev-socket.patch", "disable-netdev-socket.patch",
// fails on a slower machine
"copy-before-write-spurious.patch",
]; ];
// configure script uses source as scratch space // configure script uses source as scratch space
@@ -29,10 +35,6 @@ sed -i \
tests/qemu-iotests/[0-9][0-9][0-9]* \ tests/qemu-iotests/[0-9][0-9][0-9]* \
tests/qemu-iotests/tests/copy-before-write \ tests/qemu-iotests/tests/copy-before-write \
tests/qemu-iotests/tests/file-io-error.out tests/qemu-iotests/tests/file-io-error.out
cat << EOF > tests/qemu-iotests/150
#!/bin/sh
_notrun 'appears to spuriously fail on zfs'
EOF
`; `;
exec = make { exec = make {
@@ -56,16 +58,17 @@ EOF
check = [ check = [
"TIMEOUT_MULTIPLIER=5", "TIMEOUT_MULTIPLIER=5",
"check",
]; ];
}; };
inputs = [ inputs = [
bash, bash,
python,
python-setuptools, python-setuptools,
python-wheel, python-wheel,
meson,
ninja, ninja,
pkg-config, pkgconf,
diffutils, diffutils,
openssl, openssl,
+3 -2
View File
@@ -15,7 +15,8 @@ package rsync {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
configure = { configure = {
"disable-openssl"; "disable-openssl";
"disable-xxhash"; "disable-xxhash";
@@ -24,6 +25,6 @@ package rsync {
}; };
// circular dependency // circular dependency
skipCheck = true; check = nil;
}; };
} }
+1 -1
View File
@@ -14,7 +14,7 @@ package spirv-headers {
exec = cmake { exec = cmake {
// upstream has no tests // upstream has no tests
skipTest = true; test = nil;
}; };
} }
+3 -4
View File
@@ -28,10 +28,9 @@ package squashfs-tools {
early = "cd squashfs-tools"; early = "cd squashfs-tools";
exec = make { exec = make {
skipConfigure = true; chdir = false;
inPlace = true; configure = nil;
check = nil;
skipCheck = true;
install = "make INSTALL_PREFIX=/work/system install"; install = "make INSTALL_PREFIX=/work/system install";
}; };
+1 -1
View File
@@ -19,7 +19,7 @@ package tamago {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
mkdir /work/system/ mkdir /work/system/
cp -r . /work/system/tamago cp -r . /work/system/tamago
+8 -8
View File
@@ -22,10 +22,10 @@ package toybox {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
inPlace = true; chdir = false;
skipConfigure = true;
configure = nil;
preMake = ` preMake = `
LDFLAGS="${LDFLAGS:-''} -static" LDFLAGS="${LDFLAGS:-''} -static"
@@ -50,7 +50,7 @@ sed -i \
"USER=cure", "USER=cure",
"tests", "tests",
]; ];
skipEarlyStageCheck = true; checkEarly = false;
install = "PREFIX=/work/system/bin make install_flat"; install = "PREFIX=/work/system/bin make install_flat";
@@ -80,10 +80,10 @@ package toybox-early {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
inPlace = true; chdir = false;
skipConfigure = true;
configure = nil;
preMake = ` preMake = `
LDFLAGS="${LDFLAGS:-''} -static" LDFLAGS="${LDFLAGS:-''} -static"
@@ -115,7 +115,7 @@ CONFIG_DIFF=y
"USER=cure", "USER=cure",
"tests", "tests",
]; ];
skipEarlyStageCheck = true; checkEarly = false;
install = "PREFIX=/work/system/bin make install_flat"; install = "PREFIX=/work/system/bin make install_flat";
+1 -1
View File
@@ -20,7 +20,7 @@ package unzip {
chmod = true; chmod = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = `unix/configure build = `unix/configure
make -f unix/Makefile generic1`; make -f unix/Makefile generic1`;
install = ` install = `
+1 -1
View File
@@ -47,7 +47,7 @@ package util-linux {
// check script claims: // check script claims:
// For development purpose only. // For development purpose only.
// Don't execute on production system! // Don't execute on production system!
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
+2 -2
View File
@@ -17,14 +17,14 @@ package vim {
enterSource = true; enterSource = true;
exec = make { exec = make {
inPlace = true; chdir = false;
configure = { configure = {
"with-tlib": "ncursesw"; "with-tlib": "ncursesw";
}; };
check = [ "test" ]; check = [ "test" ];
// very expensive // very expensive
skipCheck = true; check = nil;
}; };
inputs = [ ncurses ]; inputs = [ ncurses ];
+20 -20
View File
@@ -34,7 +34,7 @@ package libxtrans {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
]; ];
@@ -59,7 +59,7 @@ package xorgproto {
inputs = [ inputs = [
automake, automake,
pkg-config, pkgconf,
util-macros, util-macros,
]; ];
@@ -121,7 +121,7 @@ package xcb {
inputs = [ inputs = [
python, python,
pkg-config, pkgconf,
xcb-proto, xcb-proto,
libXau, libXau,
@@ -148,7 +148,7 @@ package libxcb-keysyms {
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
xcb, xcb,
]; ];
@@ -172,7 +172,7 @@ package libxcb-wm {
inputs = [ inputs = [
m4, m4,
pkg-config, pkgconf,
xcb, xcb,
]; ];
@@ -196,7 +196,7 @@ package libxcb-util {
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
util-macros, util-macros,
xcb, xcb,
@@ -220,7 +220,7 @@ package libxcb-image {
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
libxcb-util, libxcb-util,
]; ];
@@ -244,7 +244,7 @@ package libxcb-render-util {
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
util-macros, util-macros,
xcb, xcb,
@@ -278,7 +278,7 @@ package libX11 {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libxtrans, libxtrans,
@@ -309,7 +309,7 @@ package libXext {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libX11, libX11,
@@ -338,7 +338,7 @@ package libXfixes {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
xorgproto, xorgproto,
@@ -368,7 +368,7 @@ package libXrender {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libX11, libX11,
@@ -397,7 +397,7 @@ package libxshmfence {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
xorgproto, xorgproto,
@@ -424,7 +424,7 @@ package libXxf86vm {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libXext, libXext,
@@ -454,7 +454,7 @@ package libXrandr {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libXext, libXext,
@@ -488,7 +488,7 @@ package font-util {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
]; ];
@@ -514,7 +514,7 @@ package libfontenc {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
font-util, font-util,
@@ -561,7 +561,7 @@ package xkbcomp {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
byacc, byacc,
util-macros, util-macros,
@@ -591,7 +591,7 @@ package libXfont2 {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
freetype, freetype,
@@ -642,7 +642,7 @@ package libXdmcp {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
xorgproto, xorgproto,
+14
View File
@@ -320,6 +320,8 @@ type PackageAttr struct {
// Whether to replace /usr/bin/ with a symlink to /bin/. // Whether to replace /usr/bin/ with a symlink to /bin/.
PopulateUsrBin bool PopulateUsrBin bool
// Whether this package is disallowed from bootstrap stages.
Std bool
// Hint for an early variant of toybox to be used when available. // Hint for an early variant of toybox to be used when available.
Early bool Early bool
// Whether to omit output colour environment variables. // Whether to omit output colour environment variables.
@@ -375,6 +377,14 @@ func (t Toolchain) Append(a []pkg.Artifact, handles ...ArtifactH) []pkg.Artifact
return a return a
} }
// A BootstrapError describes a package disallowed from bootstrap stages.
type BootstrapError string
func (e BootstrapError) Error() string {
return "package " + strconv.Quote(string(e)) +
" must not be built by bootstrap stages"
}
// New constructs a [pkg.Artifact] via a build system helper. // New constructs a [pkg.Artifact] via a build system helper.
func (t Toolchain) New( func (t Toolchain) New(
name, version string, name, version string,
@@ -387,6 +397,10 @@ func (t Toolchain) New(
attr = new(PackageAttr) attr = new(PackageAttr)
} }
if attr.Std && !t.stage.isStd() {
panic(BootstrapError(name))
}
if name == "" || version == "" { if name == "" || version == "" {
panic("name must be non-empty") panic("name must be non-empty")
} }
+46 -12
View File
@@ -811,14 +811,17 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr GenericHelper var attr GenericHelper
chdir := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("inPlace"): &attr.InPlace, k("chdir"): &chdir,
k("build"): &attr.Build, k("build"): &attr.Build,
k("check"): &attr.Check, k("check"): &attr.Check,
k("install"): &attr.Install, k("install"): &attr.Install,
}); err != nil { }); err != nil {
return return
} }
attr.InPlace = !chdir
v = &attr v = &attr
set = true set = true
return return
@@ -828,28 +831,33 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr MakeHelper var attr MakeHelper
defaults, chdir, checkEarly := true, true, true
attr.Configure, attr.Check = []KV{}, []string{}
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("omitDefaults"): &attr.OmitDefaults, k("defaults"): &defaults,
k("generate"): &attr.Generate, k("generate"): &attr.Generate,
k("preMake"): &attr.ScriptMakeEarly, k("preMake"): &attr.ScriptMakeEarly,
k("preCheck"): &attr.ScriptCheckEarly, k("preCheck"): &attr.ScriptCheckEarly,
k("postInstall"): &attr.Script, k("postInstall"): &attr.Script,
k("inPlace"): &attr.InPlace, k("chdir"): &chdir,
k("skipConfigure"): &attr.SkipConfigure,
k("configureName"): &attr.ConfigureName, k("configureName"): &attr.ConfigureName,
k("forceAutoconf"): &attr.ForceAutoconf, k("forceAutoconf"): &attr.ForceAutoconf,
k("configure"): &attr.Configure, k("configure"): &attr.Configure,
k("host"): &attr.Host, k("host"): &attr.Host,
k("build"): &attr.Build, k("build"): &attr.Build,
k("make"): &attr.Make, k("make"): &attr.Make,
k("skipCheck"): &attr.SkipCheck,
k("check"): &attr.Check, k("check"): &attr.Check,
k("install"): &attr.Install, k("install"): &attr.Install,
k("skipEarlyStageCheck"): &attr.SkipCheckEarly, k("checkEarly"): &checkEarly,
}); err != nil { }); err != nil {
return return
} }
attr.OmitDefaults, attr.InPlace = !defaults, !chdir
attr.SkipConfigure = attr.Configure == nil
attr.SkipCheck = attr.Check == nil
attr.SkipCheckEarly = !checkEarly
v = &attr v = &attr
set = true set = true
return return
@@ -859,17 +867,20 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr CMakeHelper var attr CMakeHelper
var test azalea.AString
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("append"): &attr.Append, k("append"): &attr.Append,
k("buildType"): &attr.BuildType, k("buildType"): &attr.BuildType,
k("cache"): &attr.Cache, k("cache"): &attr.Cache,
k("postInstall"): &attr.Script, k("postInstall"): &attr.Script,
k("test"): &attr.Test, k("test"): &test,
k("skipTest"): &attr.SkipTest,
k("make"): &attr.Make, k("make"): &attr.Make,
}); err != nil { }); err != nil {
return return
} }
attr.Test = test.V
attr.SkipTest = test.Nil
v = &attr v = &attr
set = true set = true
return return
@@ -879,18 +890,21 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr MesonHelper var attr MesonHelper
test := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("muon"): &attr.Muon, k("muon"): &attr.Muon,
k("preCompile"): &attr.ScriptCompileEarly, k("preCompile"): &attr.ScriptCompileEarly,
k("postCompile"): &attr.ScriptCompiled, k("postCompile"): &attr.ScriptCompiled,
k("postInstall"): &attr.Script, k("postInstall"): &attr.Script,
k("setup"): &attr.Setup, k("setup"): &attr.Setup,
k("skipTest"): &attr.SkipTest, k("test"): &test,
k("skipTests"): &attr.SkipTests, k("skipTests"): &attr.SkipTests,
k("interactiveTest"): &attr.InteractiveTest, k("interactiveTest"): &attr.InteractiveTest,
}); err != nil { }); err != nil {
return return
} }
attr.SkipTest = !test
v = &attr v = &attr
set = true set = true
return return
@@ -900,11 +914,13 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr MakeMakerHelper var attr MakeMakerHelper
doCheck := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("skipCheck"): &attr.SkipCheck, k("check"): &doCheck,
}); err != nil { }); err != nil {
return return
} }
attr.SkipCheck = !doCheck
v = &attr v = &attr
set = true set = true
return return
@@ -914,17 +930,20 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr PipHelper var attr PipHelper
var scriptCheck azalea.AString
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("append"): &attr.Append, k("append"): &attr.Append,
k("buildIsolation"): &attr.BuildIsolation, k("buildIsolation"): &attr.BuildIsolation,
k("enterSource"): &attr.EnterSource, k("enterSource"): &attr.EnterSource,
k("install"): &attr.Install, k("install"): &attr.Install,
k("skipCheck"): &attr.SkipCheck, k("check"): &scriptCheck,
k("check"): &attr.Check,
k("postInstall"): &attr.Script, k("postInstall"): &attr.Script,
}); err != nil { }); err != nil {
return return
} }
attr.Check = scriptCheck.V
attr.SkipCheck = scriptCheck.Nil
v = &attr v = &attr
set = true set = true
return return
@@ -975,6 +994,13 @@ type evalContext struct {
t Toolchain t Toolchain
} }
// HelperError describes a package with nil helper.
type HelperError string
func (e HelperError) Error() string {
return "package " + strconv.Quote(string(e)) + " has no exec helper"
}
// pf implements [azalea.PF]. // pf implements [azalea.PF].
func (ctx *evalContext) pf( func (ctx *evalContext) pf(
name azalea.Ident, name azalea.Ident,
@@ -998,6 +1024,8 @@ func (ctx *evalContext) pf(
overlay string overlay string
inputs, runtimes, extra azalea.Array inputs, runtimes, extra azalea.Array
bootstrap = true
) )
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("description"): &meta.Description, k("description"): &meta.Description,
@@ -1020,6 +1048,7 @@ func (ctx *evalContext) pf(
k("exclusive"): &attr.Exclusive, k("exclusive"): &attr.Exclusive,
k("toyboxEarly"): &attr.Early, k("toyboxEarly"): &attr.Early,
k("minimal"): &attr.NoToolchain, k("minimal"): &attr.NoToolchain,
k("bootstrap"): &bootstrap,
k("checksum"): &kc, k("checksum"): &kc,
k("output"): &output, k("output"): &output,
@@ -1032,6 +1061,7 @@ func (ctx *evalContext) pf(
}); err != nil { }); err != nil {
return return
} }
attr.Std = !bootstrap
var inputsH, extraH P var inputsH, extraH P
if inputsH, err = toHandles(inputs); err != nil { if inputsH, err = toHandles(inputs); err != nil {
return return
@@ -1149,6 +1179,10 @@ func (ctx *evalContext) pf(
} }
} }
if helper == nil {
panic(HelperError(name))
}
v = cachedArtifact{&meta, ctx.t.New( v = cachedArtifact{&meta, ctx.t.New(
meta.Name, meta.Name,
meta.Version, meta.Version,