go vet 스타일의 Linter는 reflect.SliceHeader 와 reflect.StringHeader 의 잘못된 사용을 찾으십시오.

go-safer 다음과 같은 사용 패턴을보고합니다.
reflect.StringHeader 문자가 있습니다 reflect.SliceHeaderstring 시전하여 생성되지 않은 유형의 인스턴스 인스턴스 reflect.SliceHeader 또는 reflect.StringHeader 에 대한 과제가 있습니다.int , uint 또는 uintptr 갖는 다른 수의 필드를 포함하는 구조물 유형이 있습니다.Pattern 1은 다음과 같이 보이는 코드를 식별합니다.
func unsafeFunction ( s string ) [] byte {
sH := ( * reflect . StringHeader )( unsafe . Pointer ( & s ))
bH := & reflect. SliceHeader {
Data : sH . Data ,
Len : sH . Len ,
Cap : sH . Len ,
}
return * ( * [] byte )( unsafe . Pointer ( bH ))
} 또한 type MysteryType reflect.SliceHeader 과 같이 reflect.SliceHeader 의 이름이 바뀌는 경우도 잡을 것입니다.
패턴 2는 다음과 같은 코드를 식별합니다.
func unsafeFunction ( s string ) [] byte {
strH := ( * reflect . StringHeader )( unsafe . Pointer ( & str ))
sH := ( * reflect . SliceHeader )( unsafe . Pointer ( nil ))
sH . Len = strH . Len
sH . Cap = strH . Len
sH . Data = strH . Data
return
} safer-go 할당을 유형의 객체로 가져갑니다. reflect.SliceHeader . 함수의 제어 흐름 그래프를 사용하여 실제 슬라이스를 시전하여 sH 도출되지 않았 음을 알 수 있습니다 (여기서는 대신 nil 입니다).
패턴 3 캐스트를 다음과 같이 식별합니다.
type A struct {
x int
}
type B struct {
y int64
}
func unsafeFunction ( a A ) B {
return * ( * B )( unsafe . Pointer ( & a ))
} passes/*/testdata/src 디렉토리의 테스트 사례에서 잘못된 (보고) 및 안전한 코드에 대한 더 많은 예가 있습니다.
reflect.SliceHeader 또는 reflect.StringHeader 는 실제 슬라이스 또는 string 시전하여 생성되지 않으면 GO 런타임은 이러한 유형 내에서 Data 필드를 기본 데이터 배열에 대한 참조로 처리하지 않습니다. 따라서 쓰레기 수집기가 문자 그대로의 헤더 인스턴스에서 실제 슬라이스 또는 string 으로 최종 캐스트 직전에 실행되면 원래 슬라이스 또는 string 수집 할 수 있습니다. 이로 인해 정보 유출 취약점이 생길 수 있습니다.
개념 증명 악용 및 이러한 안전하지 않은 패턴의 고정 버전에 대한 제안과 같은 자세한 내용은이 블로그 게시물을 읽으십시오.
go-safer 설치하려면 다음 명령을 사용하십시오.
go get github.com/jlauinger/go-safer
이렇게하면 go-safer $GOPATH/bin 에 설치하므로 $PATH ENVIRNING 변수에 포함되어 있는지 확인하십시오.
다음과 같은 패키지에서 Go-Safer를 실행하십시오.
$ go-safer example/cmd
또는 공간별로 분리 된 여러 패키지를 제공합니다.
$ go-safer example/cmd example/util strings
패키지를 확인하고 재귀 적으로 수입을 사용하여 사용합니다 ./... :
$ go-safer example/cmd/...
마지막으로, 현재 디렉토리에서 패키지를 확인하려면 사용할 수 있습니다 . :
$ go-safer .
go-safer go vet 과 동일한 깃발을 수락합니다.
Flags:
-V print version and exit
-all
no effect (deprecated)
-c int
display offending line with this many lines of context (default -1)
-cpuprofile string
write CPU profile to this file
-debug string
debug flags, any subset of "fpstv"
-fix
apply all suggested fixes
-flags
print analyzer flags in JSON
-json
emit JSON output
-memprofile string
write memory profile to this file
-source
no effect (deprecated)
-tags string
no effect (deprecated)
-trace string
write trace log to this file
-v no effect (deprecated)
-help 플래그 제공은 go-safer 의 사용 정보를 인쇄합니다.
$ go-safer -help
프로젝트에서 GO 모듈 및 go.mod 파일을 사용하는 경우 go-safer 분석하기 전에 모든 종속성을 자동으로 가져옵니다. 그것은 go build 와 똑같이 행동합니다.
다른 형태의 종속성 관리를 사용하는 경우, 예를 들어, 수동으로 go get , go mod vendor 또는 기타 기타 항목을 사용하는 경우 분석 전에 모든 종속성을 최신 상태로 유지하려면 go-safer 실행하기 전에 종속성 관리를 실행해야합니다.
소스 코드를 가져 와서 바이너리를 컴파일하려면 다음을 실행하십시오.
$ git clone https://github.com/jlauinger/go-safer
$ cd go-safer
$ go build
테스트 사례를 실행하려면 다음 명령을 사용하십시오.
$ go test ./...
go-safer golang.org/x/tools/go/analysis/analysistest 의 테스트 인프라를 사용합니다. 테스트 케이스를 추가하려면 passes/sliceheader/testdata/src 의 bad 디렉토리 또는 good 디렉토리 내에서 새 패키지를 만듭니다. 필요한만큼 많은 GO 파일을 패키지에 추가하십시오.
그런 다음 패키지 경로를 지정하여 sliceheader_test.go 파일에 새 패키지를 등록하십시오.
테스트 케이스 소스 파일에서보고해야 할 줄에 주석 주석을 추가하십시오. 의견은 다음과 같습니다.
sH.Len = strH.Len // want "assigning to reflect header object" "assigning to reflect header object"
fmt.Println("hello world") // ok
보고 해야하는 선을 나타내는 주석은 want 것으로 시작한 다음 원하는 메시지를 두 번 가져야합니다. 어떤 이유로, 테스트 인프라로 인해 go-safer 주석을 두 번 출력하게되므로 테스트를 통과 할 수 있도록 두 번 잘 예상되어야합니다.
structcast Pass의 테스트 케이스도 비슷하게 추가 할 수 있습니다.
go-safer Go Vet 표준 인프라를 기반으로 구축되므로 패스를 자신의 Go Vet 기반 Linter로 가져올 수 있습니다.
MIT 라이센스 ( "라이센스")에 따라 라이센스. 라이센스 준수를 제외 하고이 프로젝트를 사용할 수 없습니다. 여기에서 라이센스 사본을 얻을 수 있습니다.
Copyright 2020 Johannes Lauinger
이 도구는 TU Darmstadt의 Software Technology Group에서 마스터 논문의 일부로 개발되었습니다.