pyldb: avoid segfault when adding an element with no name
[nivanova/samba-autobuild/.git] / libcli / named_pipe_auth / tstream_u32_read.c
1 /*
2  * Unix SMB/CIFS implementation.
3  *
4  * Copyright (C) Volker Lendecke 2019
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "replace.h"
21 #include "system/filesys.h"
22 #include "tstream_u32_read.h"
23 #include "lib/util/byteorder.h"
24 #include "lib/util/tevent_unix.h"
25
26 struct tstream_u32_read_state {
27         size_t max_msglen;
28         size_t buflen;
29         uint8_t *buf;
30 };
31
32 static int tstream_u32_read_next_vector(struct tstream_context *stream,
33                                         void *private_data,
34                                         TALLOC_CTX *mem_ctx,
35                                         struct iovec **_vector,
36                                         size_t *_count);
37 static void tstream_u32_read_done(struct tevent_req *subreq);
38
39 struct tevent_req *tstream_u32_read_send(
40         TALLOC_CTX *mem_ctx,
41         struct tevent_context *ev,
42         uint32_t max_msglen,
43         struct tstream_context *stream)
44 {
45         struct tevent_req *req = NULL, *subreq = NULL;
46         struct tstream_u32_read_state *state = NULL;
47
48         req = tevent_req_create(
49                 mem_ctx, &state, struct tstream_u32_read_state);
50         if (req == NULL) {
51                 return NULL;
52         }
53         state->max_msglen = max_msglen;
54
55         subreq = tstream_readv_pdu_send(
56                 state,
57                 ev,
58                 stream,
59                 tstream_u32_read_next_vector,
60                 state);
61         if (tevent_req_nomem(subreq, req)) {
62                 return tevent_req_post(req, ev);
63         }
64         tevent_req_set_callback(subreq, tstream_u32_read_done, req);
65         return req;
66 }
67
68 static int tstream_u32_read_next_vector(struct tstream_context *stream,
69                                         void *private_data,
70                                         TALLOC_CTX *mem_ctx,
71                                         struct iovec **_vector,
72                                         size_t *_count)
73 {
74         struct tstream_u32_read_state *state = talloc_get_type_abort(
75                 private_data, struct tstream_u32_read_state);
76         size_t buflen = talloc_get_size(state->buf);
77         struct iovec *vector;
78         uint32_t msg_len;
79         size_t ofs = 0;
80         size_t count;
81
82         if (buflen == 0) {
83                 msg_len = 4;
84                 state->buf = talloc_array(state, uint8_t, msg_len);
85                 if (state->buf == NULL) {
86                         return -1;
87                 }
88         } else if (buflen == 4) {
89
90                 ofs = 4;
91
92                 msg_len = RIVAL(state->buf, 0);
93                 if ((msg_len == 0) || (msg_len > state->max_msglen)) {
94                         errno = EMSGSIZE;
95                         return -1;
96                 }
97                 msg_len += ofs;
98                 if (msg_len < ofs) {
99                         errno = EMSGSIZE;
100                         return -1;
101                 }
102
103                 state->buf = talloc_realloc(
104                         state, state->buf, uint8_t, msg_len);
105                 if (state->buf == NULL) {
106                         return -1;
107                 }
108         } else {
109                 *_vector = NULL;
110                 *_count = 0;
111                 return 0;
112         }
113
114         vector = talloc(mem_ctx, struct iovec);
115         if (vector == NULL) {
116                 return -1;
117         }
118         *vector = (struct iovec) {
119                 .iov_base = state->buf + ofs, .iov_len = msg_len - ofs,
120         };
121         count = 1;
122
123         *_vector = vector;
124         *_count = count;
125         return 0;
126 }
127
128 static void tstream_u32_read_done(struct tevent_req *subreq)
129 {
130         struct tevent_req *req = tevent_req_callback_data(
131                 subreq, struct tevent_req);
132         int ret, err;
133
134         ret = tstream_readv_pdu_recv(subreq, &err);
135         TALLOC_FREE(subreq);
136         if (ret == -1) {
137                 tevent_req_error(req, err);
138                 return;
139         }
140         tevent_req_done(req);
141 }
142
143 int tstream_u32_read_recv(
144         struct tevent_req *req,
145         TALLOC_CTX *mem_ctx,
146         uint8_t **buf,
147         size_t *buflen)
148 {
149         struct tstream_u32_read_state *state = tevent_req_data(
150                 req, struct tstream_u32_read_state);
151         int err;
152
153         if (tevent_req_is_unix_error(req, &err)) {
154                 return err;
155         }
156         *buflen = talloc_get_size(state->buf);
157         *buf = talloc_move(mem_ctx, &state->buf);
158         return 0;
159 }