@@ -24,6 +24,7 @@ import (
2424
2525 "github.com/google/syzkaller/pkg/corpus"
2626 "github.com/google/syzkaller/pkg/cover"
27+ "github.com/google/syzkaller/pkg/db"
2728 "github.com/google/syzkaller/pkg/fuzzer"
2829 "github.com/google/syzkaller/pkg/html/pages"
2930 "github.com/google/syzkaller/pkg/log"
@@ -55,6 +56,7 @@ type HTTPServer struct {
5556 Pool * vm.Dispatcher
5657 Pools map [string ]* vm.Dispatcher
5758 TogglePause func (paused bool )
59+ CorpusDB * db.DB
5860
5961 // Can be set dynamically after calling Serve.
6062 Corpus atomic.Pointer [corpus.Corpus ]
@@ -81,6 +83,7 @@ func (serv *HTTPServer) Serve() {
8183 handle ("/vms" , serv .httpVMs )
8284 handle ("/vm" , serv .httpVM )
8385 handle ("/metrics" , promhttp .HandlerFor (prometheus .DefaultGatherer , promhttp.HandlerOpts {}).ServeHTTP )
86+ handle ("/addcandidate" , serv .httpAddCandidate )
8487 handle ("/syscalls" , serv .httpSyscalls )
8588 handle ("/corpus" , serv .httpCorpus )
8689 handle ("/corpus.db" , serv .httpDownloadCorpus )
@@ -734,6 +737,46 @@ func (serv *HTTPServer) modulesInfo(w http.ResponseWriter, r *http.Request) {
734737 serv .jsonPage (w , r , "modules" , cover .Modules )
735738}
736739
740+ func (serv * HTTPServer ) httpAddCandidate (w http.ResponseWriter , r * http.Request ) {
741+ if r .Method != http .MethodPost {
742+ http .Error (w , "only POST method supported" , http .StatusMethodNotAllowed )
743+ return
744+ }
745+ err := r .ParseMultipartForm (20 << 20 )
746+ if err != nil {
747+ http .Error (w , fmt .Sprintf ("failed to parse form: %v" , err ), http .StatusBadRequest )
748+ return
749+ }
750+ file , _ , err := r .FormFile ("file" )
751+ if err != nil {
752+ http .Error (w , fmt .Sprintf ("failed to retrieve file from form-data: %v" , err ), http .StatusBadRequest )
753+ return
754+ }
755+ defer file .Close ()
756+ data , err := io .ReadAll (file )
757+ if err != nil {
758+ http .Error (w , fmt .Sprintf ("failed to read file: %v" , err ), http .StatusBadRequest )
759+ return
760+ }
761+ prog , err := ParseSeed (serv .Cfg .Target , data )
762+ if err != nil {
763+ http .Error (w , fmt .Sprintf ("failed to parse seed: %v" , err ), http .StatusBadRequest )
764+ return
765+ }
766+ if ! prog .OnlyContains (serv .Fuzzer .Load ().Config .EnabledCalls ) {
767+ http .Error (w , "contains disabled syscall" , http .StatusBadRequest )
768+ return
769+ }
770+ var flags fuzzer.ProgFlags
771+ flags |= fuzzer .ProgMinimized
772+ flags |= fuzzer .ProgSmashed
773+ candidates := []fuzzer.Candidate {{
774+ Prog : prog ,
775+ Flags : flags ,
776+ }}
777+ serv .Fuzzer .Load ().AddCandidates (candidates )
778+ }
779+
737780var alphaNumRegExp = regexp .MustCompile (`^[a-zA-Z0-9]*$` )
738781
739782func isAlphanumeric (s string ) bool {
0 commit comments