phpserialize

package module
v0.0.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 9, 2024 License: MIT Imports: 7 Imported by: 0

README

go-phpserialize

GitHub tag (latest SemVer) Go Reference

PHP serialize() and unserialize() for Go.

Support All go type including map, slice, struct, array, and simple type like int, uint ...etc.

Encoding some type from standard library like time.Time, net.IP are not supported. If you have any thought about how to support these types, please create an issue.

supported and tested go version

  • 1.18
  • 1.19
  • 1.20
  • 1.21

You may see compile error about golang_version_higher_than_*_not_supported_yet is undefined, please try to upgrade version of this package.

If you are using the latest version of this package, this is expected.

Due to the usage of unsafe (unsafe doesn't follow Go 1 promise of compatibility), new version of golang may break this package, so it use go build flags to make sure it only compile on tested go versions.

Use case:

You serialize all data into php array only.

Decoding from php serialized array or class are both supported.

Install

go get github.com/trim21/go-phpserialize
Advantage:

Low memory allocation and fast, see benchmark

Disadvantage:

heavy usage of unsafe.

Usage

Unmarshal

See examples any type will be decoded to map[any]any or map[string]any, depends on raw input is array or class,

map any key maybe int64 or string.

Security

TL;DR: Don't unmarshal content you can't trust.

Attackers may consume large memory with very few bytes.

php serialized array has a length prefix a:1:{i:0;s:3:"one";}, when decoding php serialized array into go slice or go map, go-phpserialize may call golang's make() to create a map or slice with given length.

So a malicious input like a:100000000:{} may become make([]T, 100000000) and consume high memory.

If you have to decode some un-trusted bytes, make sure only decode them into fixed-length golang array or struct, never decode them to interface, slice or map.

License

Heavily inspired by https://github.com/goccy/go-json

MIT License

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Marshal

func Marshal(v any) ([]byte, error)
Example
type User struct {
	ID   uint32 `php:"id,string"`
	Name string `php:"name"`
}

type Inner struct {
	V int    `php:"v"`
	S string `php:"a long string name replace field name"`
}

type With struct {
	Users   []User `php:"users,omitempty"`
	Obj     Inner  `php:"obj"`
	Ignored bool   `php:"-"`
}

var data = With{
	Users: []User{
		{ID: 1, Name: "sai"},
		{ID: 2, Name: "trim21"},
	},
	Obj: Inner{V: 2, S: "vvv"},
}
var b, err = phpserialize.Marshal(data)
if err != nil {
	panic(err)
}

fmt.Println(string(b))
Output:

a:2:{s:5:"users";a:2:{i:0;a:2:{s:2:"id";s:1:"1";s:4:"name";s:3:"sai";}i:1;a:2:{s:2:"id";s:1:"2";s:4:"name";s:6:"trim21";}}s:3:"obj";a:2:{s:1:"v";i:2;s:37:"a long string name replace field name";s:3:"vvv";}}

func Unmarshal

func Unmarshal(data []byte, v any) error
Example
var v struct {
	Value map[string]string `php:"value" json:"value"`
}
raw := `a:1:{s:5:"value";a:5:{s:3:"one";s:1:"1";s:3:"two";s:1:"2";s:5:"three";s:1:"3";s:4:"four";s:1:"4";s:4:"five";s:1:"5";}}`

err := phpserialize.Unmarshal([]byte(raw), &v)
if err != nil {
	panic(err)
}

fmt.Println(v.Value["five"])
Output:

5

Types

type Unmarshaler

type Unmarshaler interface {
	UnmarshalPHP([]byte) error
}

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL