nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: cilium/ebpf
Pull request #121 (2020-08-04 09:47:37)

doc: mention the link package in documentation
We now have support for attaching to some subsystems, so update
the documentation accordingly.

lmb: I'll merge this tomorrow if nobody complains.

Patch:
diff --git a/doc.go b/doc.go
index d96e6b1..f7f34da 100644
--- a/doc.go
+++ b/doc.go
@@ -12,6 +12,5 @@
 // eBPF code should be compiled ahead of time using clang, and shipped with
 // your application as any other resource.
 //
-// This package doesn't include code required to attach eBPF to Linux
-// subsystems, since this varies per subsystem.
+// Use the link subpackage to attach a loaded program to a hook in the kernel.
 package ebpf
diff --git a/link/doc.go b/link/doc.go
new file mode 100644
index 0000000..2bde35e
--- /dev/null
+++ b/link/doc.go
@@ -0,0 +1,2 @@
+// Package link allows attaching eBPF programs to various kernel hooks.
+package link
diff --git a/readme.md b/readme.md
index cc8e89c..936c09b 100644
--- a/readme.md
+++ b/readme.md
@@ -1,10 +1,11 @@
 eBPF
 -------
-[![](https://godoc.org/github.com/cilium/ebpf?status.svg)](https://godoc.org/github.com/cilium/ebpf)
+[![PkgGoDev](https://pkg.go.dev/badge/github.com/cilium/ebpf)](https://pkg.go.dev/github.com/cilium/ebpf)
 
 eBPF is a pure Go library that provides utilities for loading, compiling, and debugging eBPF programs. It has minimal external dependencies and is intended to be used in long running processes.
 
-[ebpf/asm](https://godoc.org/github.com/cilium/ebpf/asm) contains a basic assembler.
+* [ebpf/link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF to various hooks.
+* [ebpf/asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic assembler.
 
 The library is maintained by [Cloudflare](https://www.cloudflare.com) and [Cilium](https://www.cilium.io). Feel free to [join](https://cilium.herokuapp.com/) the [libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack.
 


Test patch:
diff --git a/run-tests.sh b/run-tests.sh
index c43a90d..779b407 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -21,7 +21,9 @@ if [[ "${1:-}" = "--in-vm" ]]; then
   fi
 
   echo Running tests...
-  /usr/local/bin/go test -coverprofile="$1/coverage.txt" -covermode=atomic -v -elfs "$elfs" ./...
+  # TestLibBPFCompat runs separately to pass the "-elfs" flag only for it: https://github.com/cilium/ebpf/pull/119
+  /usr/local/bin/go test -v -elfs "$elfs" -run TestLibBPFCompat
+  /usr/local/bin/go test -v ./...
   touch "$1/success"
   exit 0
 fi
@@ -78,11 +80,11 @@ if [[ ! -e "${output}/success" ]]; then
   exit 1
 else
   echo "Test successful on ${kernel_version}"
-  if [[ -v CODECOV_TOKEN ]]; then
-    curl --fail -s https://codecov.io/bash > "${tmp_dir}/codecov.sh"
-    chmod +x "${tmp_dir}/codecov.sh"
-    "${tmp_dir}/codecov.sh" -f "${output}/coverage.txt"
-  fi
+#  if [[ -v CODECOV_TOKEN ]]; then
+#    curl --fail -s https://codecov.io/bash > "${tmp_dir}/codecov.sh"
+#    chmod +x "${tmp_dir}/codecov.sh"
+#    "${tmp_dir}/codecov.sh" -f "${output}/coverage.txt"
+#  fi
 fi
 
 $sudo rm -r "${input}"
Repository: cilium/ebpf
Pull request #131 (2020-08-28 17:42:36)

Inflate BTF enum values
Inflates BTF enum values for easier access later since the link between `Spec.rawTypes` and `Spec.types` is difficult to navigate.

brycekahle: This is in support of #114 

Patch:
diff --git a/internal/btf/types.go b/internal/btf/types.go
index 264142a..3b91e9f 100644
--- a/internal/btf/types.go
+++ b/internal/btf/types.go
@@ -146,12 +146,23 @@ type Member struct {
 type Enum struct {
 	TypeID
 	Name
+	Values []EnumValue
+}
+
+// EnumValue is part of an Enum
+//
+// Is is not a valid Type
+type EnumValue struct {
+	Name
+	Value int32
 }
 
 func (e *Enum) size() uint32    { return 4 }
 func (e *Enum) walk(*copyStack) {}
 func (e *Enum) copy() Type {
 	cpy := *e
+	cpy.Values = make([]EnumValue, len(e.Values))
+	copy(cpy.Values, e.Values)
 	return &cpy
 }
 
@@ -497,7 +508,19 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
 			typ = &Union{id, name, raw.Size(), members}
 
 		case kindEnum:
-			typ = &Enum{id, name}
+			rawvals := raw.data.([]btfEnum)
+			vals := make([]EnumValue, 0, len(rawvals))
+			for i, btfVal := range rawvals {
+				name, err := rawStrings.LookupName(btfVal.NameOff)
+				if err != nil {
+					return nil, fmt.Errorf("can't get name for enum value %d: %s", i, err)
+				}
+				vals = append(vals, EnumValue{
+					Name:  name,
+					Value: btfVal.Val,
+				})
+			}
+			typ = &Enum{id, name, vals}
 
 		case kindForward:
 			typ = &Fwd{id, name}


Test patch:
diff --git a/run-tests.sh b/run-tests.sh
index 779b407..d48b848 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -22,7 +22,7 @@ if [[ "${1:-}" = "--in-vm" ]]; then
 
   echo Running tests...
   # TestLibBPFCompat runs separately to pass the "-elfs" flag only for it: https://github.com/cilium/ebpf/pull/119
-  /usr/local/bin/go test -v -elfs "$elfs" -run TestLibBPFCompat
+  /usr/local/bin/go test -v -run TestLibBPFCompat -elfs "$elfs"
   /usr/local/bin/go test -v ./...
   touch "$1/success"
   exit 0
Repository: cilium/ebpf
Pull request #144 (2020-10-01 14:37:40)

map, program: deprecate ABI()
Add explicit getters for fields that are currently exported via
ABI() and mark the functions as deprecated. They will be removed
in a follow up PR.

lmb: @arthurfabre I know that you use MapABI.Equal for `xdpcap`, can you take a look at this PR? The follow up is going to remove the ABI structs and ABI.Equal completely, I hope that isn't too onerous for xdpcap.

Patch:
diff --git a/map.go b/map.go
index 64decb1..aa02cdf 100644
--- a/map.go
+++ b/map.go
@@ -269,7 +269,29 @@ func (m *Map) String() string {
 	return fmt.Sprintf("%s#%v", m.abi.Type, m.fd)
 }
 
-// ABI gets the ABI of the Map
+// Type returns the underlying type of the map.
+func (m *Map) Type() MapType {
+	return m.abi.Type
+}
+
+// KeySize returns the size of the map key in bytes.
+func (m *Map) KeySize() uint32 {
+	return m.abi.KeySize
+}
+
+// ValueSize returns the size of the map value in bytes.
+func (m *Map) ValueSize() uint32 {
+	return m.abi.ValueSize
+}
+
+// MaxEntries returns the maximum number of elements the map can hold.
+func (m *Map) MaxEntries() uint32 {
+	return m.abi.MaxEntries
+}
+
+// ABI gets the ABI of the Map.
+//
+// Deprecated: use Type, KeySize, ValueSize, MaxEntries instead.
 func (m *Map) ABI() MapABI {
 	return m.abi
 }
diff --git a/perf/reader.go b/perf/reader.go
index 9e469a9..195d2c4 100644
--- a/perf/reader.go
+++ b/perf/reader.go
@@ -191,7 +191,7 @@ func NewReaderWithOptions(array *ebpf.Map, perCPUBuffer int, opts ReaderOptions)
 
 	var (
 		fds      = []int{epollFd}
-		nCPU     = int(array.ABI().MaxEntries)
+		nCPU     = int(array.MaxEntries())
 		rings    = make([]*perfEventRing, 0, nCPU)
 		pauseFds = make([]int, 0, nCPU)
 	)
diff --git a/prog.go b/prog.go
index bf1c799..bb38f21 100644
--- a/prog.go
+++ b/prog.go
@@ -276,7 +276,14 @@ func (p *Program) String() string {
 	return fmt.Sprintf("%s#%v", p.abi.Type, p.fd)
 }
 
-// ABI gets the ABI of the Program
+// Type returns the underlying type of the program.
+func (p *Program) Type() ProgramType {
+	return p.abi.Type
+}
+
+// ABI gets the ABI of the Program.
+//
+// Deprecated: use Type instead.
 func (p *Program) ABI() ProgramABI {
 	return p.abi
 }


Test patch:
diff --git a/collection_test.go b/collection_test.go
index 484e84e..0918892 100644
--- a/collection_test.go
+++ b/collection_test.go
@@ -308,8 +308,8 @@ func ExampleCollectionSpec_LoadAndAssign() {
 		panic(err)
 	}
 
-	fmt.Println(objs.Program.ABI().Type)
-	fmt.Println(objs.Map.ABI().Type)
+	fmt.Println(objs.Program.Type())
+	fmt.Println(objs.Map.Type())
 
 	// Output: SocketFilter
 	// Array
@@ -349,8 +349,8 @@ func ExampleCollection_Assign() {
 		panic(err)
 	}
 
-	fmt.Println(objs.Program.ABI().Type)
-	fmt.Println(objs.Map.ABI().Type)
+	fmt.Println(objs.Program.Type())
+	fmt.Println(objs.Map.Type())
 
 	// Output: SocketFilter
 	// Array
Repository: cilium/ebpf
Pull request #154 (2020-11-09 10:50:54)

CI: test on 5.9 kernel
Include 5.9 kernel in tests.


Patch:
diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml
index a444f5b..c86a191 100644
--- a/.semaphore/semaphore.yml
+++ b/.semaphore/semaphore.yml
@@ -32,7 +32,7 @@ blocks:
           - env_var: GO_VERSION
             values: [ "1.14", "1.15" ]
           - env_var: KERNEL_VERSION
-            values: ["5.4", "4.19", "4.9"]
+            values: ["5.9", "5.4", "4.19", "4.9"]
         commands:
           - sem-version go $GO_VERSION
           - timeout -s KILL 600s ./run-tests.sh $KERNEL_VERSION


Test patch:
diff --git a/elf_reader_test.go b/elf_reader_test.go
index 968bef5..e92e0a2 100644
--- a/elf_reader_test.go
+++ b/elf_reader_test.go
@@ -224,9 +224,20 @@ func TestLibBPFCompat(t *testing.T) {
 	}
 
 	testutils.TestFiles(t, filepath.Join(*elfPath, *elfPattern), func(t *testing.T, path string) {
+		file := filepath.Base(path)
+		switch file {
+		case "test_ksyms.o":
+			// Issue #114
+			t.Skip("Kernel symbols not supported")
+		case "test_sk_assign.o":
+			t.Skip("Incompatible struct bpf_map_def")
+		case "test_ringbuf_multi.o", "map_ptr_kern.o", "test_btf_map_in_map.o":
+			// Issue #155
+			t.Skip("BTF .values not supported")
+		}
+
 		t.Parallel()
 
-		file := filepath.Base(path)
 		_, err := LoadCollectionSpec(path)
 		testutils.SkipIfNotSupported(t, err)
 		if err != nil {
Repository: cilium/ebpf
Pull request #165 (2020-11-17 15:34:28)

btf: add go-fuzz targets
Add two targets for go-fuzz, for further experimentation. A short run already found an OOM condition, so I'm sure there is lots more to discover.


Patch:
diff --git a/internal/btf/ext_info.go b/internal/btf/ext_info.go
index 9df1b31..c1c82ec 100644
--- a/internal/btf/ext_info.go
+++ b/internal/btf/ext_info.go
@@ -130,6 +130,8 @@ func (ei extInfo) MarshalBinary() ([]byte, error) {
 }
 
 func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]extInfo, error) {
+	const maxRecordSize = 256
+
 	var recordSize uint32
 	if err := binary.Read(r, bo, &recordSize); err != nil {
 		return nil, fmt.Errorf("can't read record size: %v", err)
@@ -139,6 +141,9 @@ func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[st
 		// Need at least insnOff
 		return nil, errors.New("record size too short")
 	}
+	if recordSize > maxRecordSize {
+		return nil, fmt.Errorf("record size %v exceeds %v", recordSize, maxRecordSize)
+	}
 
 	result := make(map[string]extInfo)
 	for {
diff --git a/internal/btf/fuzz.go b/internal/btf/fuzz.go
new file mode 100644
index 0000000..37e043f
--- /dev/null
+++ b/internal/btf/fuzz.go
@@ -0,0 +1,49 @@
+// +build gofuzz
+
+// Use with https://github.com/dvyukov/go-fuzz
+
+package btf
+
+import (
+	"bytes"
+	"encoding/binary"
+
+	"github.com/cilium/ebpf/internal"
+)
+
+func FuzzSpec(data []byte) int {
+	if len(data) < binary.Size(btfHeader{}) {
+		return -1
+	}
+
+	spec, err := loadNakedSpec(bytes.NewReader(data), internal.NativeEndian, nil, nil)
+	if err != nil {
+		if spec != nil {
+			panic("spec is not nil")
+		}
+		return 0
+	}
+	if spec == nil {
+		panic("spec is nil")
+	}
+	return 1
+}
+
+func FuzzExtInfo(data []byte) int {
+	if len(data) < binary.Size(btfExtHeader{}) {
+		return -1
+	}
+
+	table := stringTable("\x00foo\x00barfoo\x00")
+	info, err := parseExtInfo(bytes.NewReader(data), internal.NativeEndian, table)
+	if err != nil {
+		if info != nil {
+			panic("info is not nil")
+		}
+		return 0
+	}
+	if info == nil {
+		panic("info is nil")
+	}
+	return 1
+}


Test patch:
diff --git a/internal/btf/ext_info_test.go b/internal/btf/ext_info_test.go
new file mode 100644
index 0000000..5b80665
--- /dev/null
+++ b/internal/btf/ext_info_test.go
@@ -0,0 +1,17 @@
+package btf
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/cilium/ebpf/internal"
+)
+
+func TestParseExtInfoBigRecordSize(t *testing.T) {
+	rd := strings.NewReader("\xff\xff\xff\xff\x00\x00\x00\x000709171295166016")
+	table := stringTable("\x00")
+	_, err := parseExtInfo(rd, internal.NativeEndian, table)
+	if err == nil {
+		t.Error("Parsing ext info with large record size doesn't return an error")
+	}
+}
Repository: cilium/ebpf
Pull request #282 (2021-04-12 18:58:48)

link/kprobe: parse retprobe bit
Closes https://github.com/cilium/ebpf/issues/275


Patch:
diff --git a/link/kprobe.go b/link/kprobe.go
index 9366628..9e519c2 100644
--- a/link/kprobe.go
+++ b/link/kprobe.go
@@ -1,12 +1,15 @@
 package link
 
 import (
+	"bytes"
 	"crypto/rand"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"runtime"
+	"sync"
 
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf/internal"
@@ -15,6 +18,12 @@ import (
 
 var (
 	kprobeEventsPath = filepath.Join(tracefsPath, "kprobe_events")
+
+	kprobeRetprobeBit = struct {
+		once  sync.Once
+		value uint64
+		err   error
+	}{}
 )
 
 // Kprobe attaches the given eBPF program to a perf event that fires when the
@@ -117,16 +126,19 @@ func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
 		return nil, err
 	}
 
-	// TODO: Parse the position of the bit from /sys/bus/event_source/devices/%s/format/retprobe.
-	config := 0
+	var config uint64
 	if ret {
-		config = 1
+		retprobeBit, err := kretprobeBit()
+		if err != nil {
+			return nil, fmt.Errorf("determine kretprobe bit: %w", err)
+		}
+		config |= 1 << retprobeBit
 	}
 
 	attr := unix.PerfEventAttr{
 		Type:   uint32(et),          // PMU event type read from sysfs
 		Ext1:   uint64(uintptr(sp)), // Kernel symbol to trace
-		Config: uint64(config),      // perf_kprobe PMU treats config as flags
+		Config: config,              // Set retprobe for k,uretprobes
 	}
 
 	fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
@@ -294,3 +306,32 @@ func kprobePrefix(ret bool) string {
 	}
 	return "p"
 }
+
+// determineRetprobeBit reads a Performance Monitoring Unit's retprobe bit
+// from /sys/bus/event_source/devices/<pmu>/format/retprobe.
+func determineRetprobeBit(pmu string) (uint64, error) {
+	p := filepath.Join("/sys/bus/event_source/devices/", pmu, "/format/retprobe")
+
+	data, err := ioutil.ReadFile(p)
+	if err != nil {
+		return 0, err
+	}
+
+	var rp uint64
+	n, err := fmt.Sscanf(string(bytes.TrimSpace(data)), "config:%d", &rp)
+	if err != nil {
+		return 0, fmt.Errorf("parse retprobe bit: %w", err)
+	}
+	if n != 1 {
+		return 0, fmt.Errorf("parse retprobe bit: expected 1 item, got %d", n)
+	}
+
+	return rp, nil
+}
+
+func kretprobeBit() (uint64, error) {
+	kprobeRetprobeBit.once.Do(func() {
+		kprobeRetprobeBit.value, kprobeRetprobeBit.err = determineRetprobeBit("kprobe")
+	})
+	return kprobeRetprobeBit.value, kprobeRetprobeBit.err
+}


Test patch:
diff --git a/link/kprobe_test.go b/link/kprobe_test.go
index 472a9f6..e02a141 100644
--- a/link/kprobe_test.go
+++ b/link/kprobe_test.go
@@ -270,3 +270,15 @@ func TestKprobeTraceFSGroup(t *testing.T) {
 	_, err = randomGroup("/")
 	c.Assert(err, qt.Not(qt.IsNil))
 }
+
+func TestDetermineRetprobeBit(t *testing.T) {
+	testutils.SkipOnOldKernel(t, "4.17", "perf_kprobe PMU")
+	c := qt.New(t)
+
+	rp, err := kretprobeBit()
+	c.Assert(err, qt.IsNil)
+	c.Assert(rp, qt.Equals, uint64(0))
+
+	_, err = determineRetprobeBit("bogus")
+	c.Assert(errors.Is(err, os.ErrNotExist), qt.IsTrue, qt.Commentf("got error: %s", err))
+}
Repository: ethereum/web3.py
Pull request #3525 (2024-11-07 08:06:34)

add check bytes length in get_create2_address
### What was wrong?

I did not correctly determine the address through the create 2 opcode, I thought I had a problem with the smart contract, but it turns out that the length of the salt should be 32 bytes, this was not checked in web3 py

### How was it fixed?

added a check

### Todo:

- [x] Clean up commit history
- [x] Add entry to the [release notes](https://github.com/ethereum/web3.py/blob/main/newsfragments/README.md)

fselmo: This is a nice addition. Thanks @artemki2077. I added some tests and a newsfragment and made some slight tweaks.

Patch:
diff --git a/newsfragments/3525.misc.rst b/newsfragments/3525.misc.rst
new file mode 100644
index 00000000..07b7eec0
--- /dev/null
+++ b/newsfragments/3525.misc.rst
@@ -0,0 +1,1 @@
+Validate the salt length as 32 bytes for ``web3.utils.address.get_create2_address``.
diff --git a/web3/utils/address.py b/web3/utils/address.py
index c85e6669..4fc6d00c 100644
--- a/web3/utils/address.py
+++ b/web3/utils/address.py
@@ -9,6 +9,9 @@ from eth_utils import (
 )
 import rlp
 
+from web3.exceptions import (
+    Web3ValidationError,
+)
 from web3.types import (
     HexStr,
     Nonce,
@@ -30,6 +33,11 @@ def get_create2_address(
     Determine the resulting `CREATE2` opcode contract address for a sender, salt and
     bytecode.
     """
+    if len(to_bytes(hexstr=salt)) != 32:
+        raise Web3ValidationError(
+            f"`salt` must be 32 bytes, {len(to_bytes(hexstr=salt))} != 32"
+        )
+
     contract_address = keccak(
         b"\xff"
         + to_bytes(hexstr=sender)


Test patch:
diff --git a/tests/core/utilities/test_address.py b/tests/core/utilities/test_address.py
index 8f5e7b8f..937c1135 100644
--- a/tests/core/utilities/test_address.py
+++ b/tests/core/utilities/test_address.py
@@ -1,5 +1,8 @@
 import pytest
 
+from web3.exceptions import (
+    Web3ValidationError,
+)
 from web3.utils.address import (
     get_create2_address,
     get_create_address,
@@ -69,3 +72,16 @@ def test_address_get_create_address(sender, nonce, expected):
 def test_address_get_create2_address(sender, salt, init_code, expected):
     actual = get_create2_address(sender, salt, init_code)
     assert actual == expected
+
+
+@pytest.mark.parametrize(
+    "salt",
+    ("0x", "0x00", "0x0000", f"0x{'00' * 31}", f"0x{'00' * 33}"),
+)
+def test_salt_length_validation(salt):
+    with pytest.raises(Web3ValidationError):
+        get_create2_address(
+            f"0x{'00' * 20}",
+            salt,
+            "0x00",
+        )
Repository: hedhyw/json-log-viewer
Pull request #23 (2023-08-05 04:02:41)

fix: special characters


Patch:
diff --git a/internal/pkg/source/entry.go b/internal/pkg/source/entry.go
index 8844443..8d1d333 100644
--- a/internal/pkg/source/entry.go
+++ b/internal/pkg/source/entry.go
@@ -3,6 +3,8 @@ package source
 import (
 	"bytes"
 	"encoding/json"
+	"strings"
+	"unicode"
 
 	"github.com/charmbracelet/bubbles/table"
 	"github.com/valyala/fastjson"
@@ -79,15 +81,29 @@ func ParseLogEntry(line json.RawMessage) LogEntry {
 		return LogEntry{
 			Line:    line,
 			Time:    "-",
-			Message: string(line),
+			Message: formatMessage(string(line)),
 			Level:   LevelUnknown,
 		}
 	}
 
 	return LogEntry{
 		Line:    line,
-		Time:    extractTime(value),
-		Message: extractMessage(value),
+		Time:    formatMessage(extractTime(value)),
+		Message: formatMessage(extractMessage(value)),
 		Level:   extractLevel(value),
 	}
 }
+
+func formatMessage(msg string) string {
+	msg = strings.NewReplacer("\n", "\\n", "\t", "\\t").Replace(msg)
+
+	msg = strings.Map(func(r rune) rune {
+		if unicode.IsPrint(r) {
+			return r
+		}
+
+		return -1
+	}, msg)
+
+	return msg
+}
diff --git a/internal/pkg/source/helper.go b/internal/pkg/source/helper.go
index bbfc78e..a7fa8ea 100644
--- a/internal/pkg/source/helper.go
+++ b/internal/pkg/source/helper.go
@@ -10,7 +10,7 @@ import (
 func extractTime(value *fastjson.Value) string {
 	timeValue := extractValue(value, "timestamp", "time", "t")
 	if timeValue != "" {
-		return strings.TrimSpace(timeValue)
+		return formatMessage(strings.TrimSpace(timeValue))
 	}
 
 	return "-"
@@ -19,7 +19,7 @@ func extractTime(value *fastjson.Value) string {
 func extractLevel(value *fastjson.Value) Level {
 	level := extractValue(value, "level", "lvl")
 
-	return ParseLevel(level)
+	return ParseLevel(formatMessage(level))
 }
 
 func extractValue(value *fastjson.Value, keys ...string) string {


Test patch:
diff --git a/internal/pkg/source/entry_test.go b/internal/pkg/source/entry_test.go
index 1da1a93..dd8b2ae 100644
--- a/internal/pkg/source/entry_test.go
+++ b/internal/pkg/source/entry_test.go
@@ -75,6 +75,14 @@ func TestParseLogEntry(t *testing.T) {
 
 			assert.Equal(t, "msg", logEntry.Message)
 		},
+	}, {
+		Name: "message_special_rune",
+		JSON: `{"message":"mes` + string(rune(1)) + `sage"}`,
+		Assert: func(tb testing.TB, logEntry source.LogEntry) {
+			tb.Helper()
+
+			assert.Equal(t, "message", logEntry.Message)
+		},
 	}, {
 		Name: "error",
 		JSON: `{"error":"error"}`,
Repository: hedhyw/json-log-viewer
Pull request #27 (2023-09-07 16:40:15)

feat: Support ts as time field
## Description

This pull request adds support for the 'ts' field in addition to 'timestamp', 'time', and 't' as valid time fields when extracting time values from JSON data.


## Changes Made

- Modified the `extractTime` function to recognize 'ts' as a valid time field.
- Updated unit tests to account for the new time field.


Patch:
diff --git a/internal/pkg/source/helper.go b/internal/pkg/source/helper.go
index a7fa8ea..402ce44 100644
--- a/internal/pkg/source/helper.go
+++ b/internal/pkg/source/helper.go
@@ -8,7 +8,7 @@ import (
 )
 
 func extractTime(value *fastjson.Value) string {
-	timeValue := extractValue(value, "timestamp", "time", "t")
+	timeValue := extractValue(value, "timestamp", "time", "t", "ts")
 	if timeValue != "" {
 		return formatMessage(strings.TrimSpace(timeValue))
 	}


Test patch:
diff --git a/internal/pkg/source/entry_test.go b/internal/pkg/source/entry_test.go
index dd8b2ae..0a8b0a5 100644
--- a/internal/pkg/source/entry_test.go
+++ b/internal/pkg/source/entry_test.go
@@ -44,6 +44,14 @@ func TestParseLogEntry(t *testing.T) {
 			assert.Equal(t, "1", logEntry.Time)
 		},
 	}, {
+		Name: "ts_number",
+		JSON: `{"ts":1}`,
+		Assert: func(tb testing.TB, logEntry source.LogEntry) {
+			tb.Helper()
+
+			assert.Equal(t, "1", logEntry.Time)
+		},
+	}, {
 		Name: "time_text",
 		JSON: `{"time":"1970-01-01T00:00:00.00"}`,
 		Assert: func(tb testing.TB, logEntry source.LogEntry) {
@@ -60,6 +68,14 @@ func TestParseLogEntry(t *testing.T) {
 			assert.Equal(t, "1970-01-01T00:00:00.00", logEntry.Time)
 		},
 	}, {
+		Name: "ts_text",
+		JSON: `{"ts":"1970-01-01T00:00:00.00"}`,
+		Assert: func(tb testing.TB, logEntry source.LogEntry) {
+			tb.Helper()
+
+			assert.Equal(t, "1970-01-01T00:00:00.00", logEntry.Time)
+		},
+	}, {
 		Name: "message",
 		JSON: `{"message":"message"}`,
 		Assert: func(tb testing.TB, logEntry source.LogEntry) {