1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <lib/fidl/coding.h>
6 
7 #include <stdalign.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 
11 #include <lib/fidl/internal.h>
12 #include <zircon/assert.h>
13 #include <zircon/compiler.h>
14 
15 #include "buffer_walker.h"
16 
17 // TODO(kulakowski) Design zx_status_t error values.
18 
19 namespace {
20 
21 class FidlValidator final : public fidl::internal::BufferWalker<FidlValidator, false, false> {
22     typedef fidl::internal::BufferWalker<FidlValidator, false, false> Super;
23 
24 public:
FidlValidator(const fidl_type_t * type,const void * bytes,uint32_t num_bytes,uint32_t num_handles,const char ** out_error_msg)25     FidlValidator(const fidl_type_t* type, const void* bytes, uint32_t num_bytes,
26                   uint32_t num_handles, const char** out_error_msg)
27         : Super(type), bytes_(static_cast<const uint8_t*>(bytes)), num_bytes_(num_bytes),
28           num_handles_(num_handles), out_error_msg_(out_error_msg) {}
29 
Walk()30     void Walk() {
31         Super::Walk();
32         if (status_ == ZX_OK && handle_idx() != num_handles()) {
33             SetError("message did not contain the specified number of handles");
34             return;
35         }
36     }
37 
bytes() const38     const uint8_t* bytes() const { return bytes_; }
num_bytes() const39     uint32_t num_bytes() const { return num_bytes_; }
num_handles() const40     uint32_t num_handles() const { return num_handles_; }
41 
ValidateOutOfLineStorageClaim(const void * a,const void * b)42     bool ValidateOutOfLineStorageClaim(const void* a, const void* b) {
43         return true;
44     }
45 
UnclaimedHandle(const zx_handle_t * out_handle)46     void UnclaimedHandle(const zx_handle_t* out_handle) {}
ClaimedHandle(const zx_handle_t * out_handle,uint32_t idx)47     void ClaimedHandle(const zx_handle_t* out_handle, uint32_t idx) {}
48 
49     template <class T>
UpdatePointer(const T * const * p,const T * v)50     void UpdatePointer(const T* const* p, const T* v) {}
51 
GetPointerState(const void * ptr) const52     PointerState GetPointerState(const void* ptr) const {
53         return static_cast<PointerState>(*static_cast<const uintptr_t*>(ptr));
54     }
GetHandleState(zx_handle_t p) const55     HandleState GetHandleState(zx_handle_t p) const {
56         return static_cast<HandleState>(p);
57     }
58 
SetError(const char * error_msg)59     void SetError(const char* error_msg) {
60         status_ = ZX_ERR_INVALID_ARGS;
61         if (out_error_msg_ != nullptr) {
62             *out_error_msg_ = error_msg;
63         }
64     }
65 
status() const66     zx_status_t status() const { return status_; }
67 
68 private:
69     // Message state passed in to the constructor.
70     const uint8_t* const bytes_;
71     const uint32_t num_bytes_;
72     const uint32_t num_handles_;
73     const char** const out_error_msg_;
74     zx_status_t status_ = ZX_OK;
75 };
76 
77 } // namespace
78 
fidl_validate(const fidl_type_t * type,const void * bytes,uint32_t num_bytes,uint32_t num_handles,const char ** out_error_msg)79 zx_status_t fidl_validate(const fidl_type_t* type, const void* bytes, uint32_t num_bytes,
80                           uint32_t num_handles, const char** out_error_msg) {
81     FidlValidator validator(type, bytes, num_bytes, num_handles, out_error_msg);
82     validator.Walk();
83     return validator.status();
84 }
85 
fidl_validate_msg(const fidl_type_t * type,const fidl_msg_t * msg,const char ** out_error_msg)86 zx_status_t fidl_validate_msg(const fidl_type_t* type, const fidl_msg_t* msg,
87                               const char** out_error_msg) {
88     return fidl_validate(type, msg->bytes, msg->num_bytes, msg->num_handles,
89                          out_error_msg);
90 }
91