programing

어떤 입력이 골랑의 json을 발생시키는지.오류를 반환할 보안요원?

madecode 2023. 3. 14. 22:04
반응형

어떤 입력이 골랑의 json을 발생시키는지.오류를 반환할 보안요원?

문서에서:

JSON은 순환 데이터 구조를 나타낼 수 없으며 Marshal은 이러한 구조를 처리하지 않습니다.순환 구조를 Marshal에게 전달하면 무한 재귀가 발생합니다.

런타임 패닉을 일으키는 이 상황을 경험했습니다.

내가 궁금한 것은 json이 패닉에 빠지지 않는 상황을 보여주는 프로그램을 제공할 수 있는 사람이 있느냐는 것이다.Marshal이 nil 이외의 오류를 반환합니다.최선의 답변에는 사용된 입력이 포함됩니다.

조나단의 대답을 보완하기 위해서죠, json.Marshal 함수는 다음 두 가지 유형의 오류를 반환할 수 있습니다.UnsupportedTypeError또는UnsupportedValueError

조나단이 말한 것처럼 첫 번째 유형은 유효하지 않은 유형으로 분류하려고 하면 발생할 수 있습니다.

_, err := json.Marshal(make(chan int))
_, ok := err.(*json.UnsupportedTypeError) // ok == true

한편, Marshal 함수가 잘못된 값을 전달하여 오류를 반환하도록 할 수도 있습니다.

_, err := json.Marshal(math.Inf(1))
_, ok := err.(*json.UnsupportedValueError) // ok == true

업데이트: 이제 오류를 유도하기 위해 map[int]int 대신 채널을 사용합니다.


특정 구조, 예를 들어func또는chan연재 거부:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    value := make(chan int)
    _, err := json.Marshal(value)
    fmt.Println(err)
}

찾을 수 있는 소스 코드를 읽고 인코더가 존재하지 않으면 marshal 오류가 반환된다고 판단합니다.https://github.com/golang/go/blob/master/src/encoding/json/encode.go

func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
    // ignored
    switch t.Kind() {
    case reflect.Bool:
        return boolEncoder
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        return intEncoder
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
        return uintEncoder
    case reflect.Float32:
        return float32Encoder
    case reflect.Float64:
        return float64Encoder
    case reflect.String:
        return stringEncoder
    case reflect.Interface:
        return interfaceEncoder
    case reflect.Struct:
        return newStructEncoder(t)
    case reflect.Map:
        return newMapEncoder(t)
    case reflect.Slice:
        return newSliceEncoder(t)
    case reflect.Array:
        return newArrayEncoder(t)
    case reflect.Ptr:
        return newPtrEncoder(t)
    default:
        return unsupportedTypeEncoder
    }
}

모든 종류의 열거형은 https://github.com/golang/go/blob/master/src/reflect/type.go에서 찾을 수 있습니다.

따라서 위의 함수에 포함되지 않은 종류가 분류할 수 없는 것은 어렵지 않습니다.

UnsafePointer,Complex64,Complex128,Chan,Func

예:

        json.Marshal(unsafe.Pointer(nil)) // UnsafePointer
        json.Marshal(complex64(1))        // Complex64
        json.Marshal(complex128(1))       // Complex128
        json.Marshal(make(chan struct{})) // Chan
        json.Marshal(func() {})           // Func

얼마 전 골랑에서 순환 참조를 직렬화/비직렬화하는 문제를 해결하고 있었는데, 모든 링크가 이 질문으로 넘어갑니다.하지만 질문이 넓어서 조금 오해의 소지가 있습니다.

저와 같은 상황에 처해서 순환 참조에 대한 해결책을 찾을 수 없다면, 이제 제가 github에 게시한 새로운 라이브러리인 tahwil을 사용할 수 있습니다.제가 아는 바로는 현재 일반적인 방법으로 순환 데이터 구조의 직렬화/비직렬화를 지원하는 유일한 라이브러리입니다.

Readme는 라이브러리 사용 방법에 대한 정보를 제공하므로 여기서는 예시만 복제합니다.

인코딩:

package main

import (
    "encoding/json"
    "fmt"

    "github.com/go-extras/tahwil"
)

type Person struct {
    Name     string
    Parent   *Person
    Children []*Person
}

func main() {
    parent := &Person{
        Name: "Arthur",
        Children: []*Person{
            {
                Name: "Ford",
            },
            {
                Name: "Trillian",
            },
        },
    }
    parent.Children[0].Parent = parent
    parent.Children[1].Parent = parent
    v, err := tahwil.ToValue(parent)
    if err != nil {
        panic(err)
    }
    res, err := json.Marshal(v)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(res))
}

디코딩:

package main

import (
    "encoding/json"
    "fmt"

    "github.com/go-extras/tahwil"
)

type Person struct {
    Name     string    `json:"name"`
    Parent   *Person   `json:"parent"`
    Children []*Person `json:"children"`
}

func prepareData() []byte {
    parent := &Person{
        Name: "Arthur",
        Children: []*Person{
            {
                Name: "Ford",
            },
            {
                Name: "Trillian",
            },
        },
    }
    parent.Children[0].Parent = parent
    parent.Children[1].Parent = parent
    v, err := tahwil.ToValue(parent)
    if err != nil {
        panic(err)
    }
    res, err := json.Marshal(v)
    if err != nil {
        panic(err)
    }
    return res
}

func main() {
    data := &tahwil.Value{}
    res := prepareData()
    err := json.Unmarshal(res, data)
    if err != nil {
        panic(err)
    }
    person := &Person{}
    err = tahwil.FromValue(data, person)
    if err != nil {
        panic(err)
    }
    fmt.Printf(`Name: %s
Children:
    - %s
    -- parent name: %s
    - %s
    -- parent name: %s
`, person.Name,
        person.Children[0].Name,
        person.Children[0].Parent.Name,
        person.Children[1].Name,
        person.Children[1].Parent.Name)
}

주요 아이디어는 원본 데이터를 다음과 같이 변환하는 것입니다.tahwil.Value{}즉, 기본적으로는refid모든 분야를 대상으로 합니다.언제든지tahwil는 순환 참조를 발견하면 실제 객체를 참조로 바꿉니다.그 후 그래프는 기술적으로 더 이상 순환적이지 않으므로 json으로 마샬링할 수 있습니다.

데이터 복원은 역연산을 의미합니다. 즉, 참조는 객체에 대한 포인터로 대체됩니다.

왜?tahwil이름에서 특이한 단어를 찾았는데 아랍어로 변환이라는 뜻의 단어(ت는 것)가 나왔어요.

언급URL : https://stackoverflow.com/questions/33903552/what-input-will-cause-golangs-json-marshal-to-return-an-error

반응형