1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hdf_log.h"
10 #include "hdf_sbuf.h"
11 #include "hdf_sbuf_impl.h"
12 #include "osal_mem.h"
13 #include "securec.h"
14
15 #define HDF_SBUF_GROW_SIZE_DEFAULT 256
16 #define HDF_SBUF_MAX_SIZE (512 * 1024) // 512KB
17 #define HDF_SBUF_ALIGN 4
18
19 #ifndef INT16_MAX
20 #ifdef S16_MAX
21 #define INT16_MAX S16_MAX
22 #else
23 #define INT16_MAX 32767
24 #endif // !S16_MAX
25 #endif // INT16_MAX
26
27 struct HdfSBufRaw {
28 struct HdfSBufImpl infImpl;
29 size_t writePos; /**< Current write position */
30 size_t readPos; /**< Current read position */
31 size_t capacity; /**< Storage capacity, 512 KB at most. */
32 uint8_t *data; /**< Pointer to data storage */
33 bool isBind; /**< Whether to bind the externally transferred pointer to data storage */
34 };
35
36 #define SBUF_RAW_CAST(impl) (struct HdfSBufRaw *)(impl)
37
38 static struct HdfSBufRaw *SbufRawImplNewInstance(size_t capacity);
39 static void SbufInterfaceAssign(struct HdfSBufImpl *inf);
40
SbufRawImplGetAlignSize(size_t size)41 static size_t SbufRawImplGetAlignSize(size_t size)
42 {
43 return (size + HDF_SBUF_ALIGN - 1) & (~(HDF_SBUF_ALIGN - 1));
44 }
45
SbufRawImplRecycle(struct HdfSBufImpl * impl)46 static void SbufRawImplRecycle(struct HdfSBufImpl *impl)
47 {
48 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
49 if (sbuf != NULL) {
50 if (sbuf->data != NULL && !sbuf->isBind) {
51 OsalMemFree(sbuf->data);
52 }
53 OsalMemFree(sbuf);
54 }
55 }
56
SbufRawImplGetLeftWriteSize(struct HdfSBufRaw * sbuf)57 static size_t SbufRawImplGetLeftWriteSize(struct HdfSBufRaw *sbuf)
58 {
59 return (sbuf->capacity < sbuf->writePos) ? 0 : (sbuf->capacity - sbuf->writePos);
60 }
61
SbufRawImplGetLeftReadSize(struct HdfSBufRaw * sbuf)62 static size_t SbufRawImplGetLeftReadSize(struct HdfSBufRaw *sbuf)
63 {
64 return (sbuf->writePos < sbuf->readPos) ? 0 : (sbuf->writePos - sbuf->readPos);
65 }
66
SbufRawImplWriteRollback(struct HdfSBufImpl * impl,uint32_t size)67 static bool SbufRawImplWriteRollback(struct HdfSBufImpl *impl, uint32_t size)
68 {
69 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
70 size_t alignSize;
71 if (sbuf == NULL) {
72 return false;
73 }
74
75 alignSize = SbufRawImplGetAlignSize(size);
76 if (sbuf->writePos < alignSize) {
77 return false;
78 }
79
80 sbuf->writePos -= alignSize;
81 return true;
82 }
83
SbufRawImplReadRollback(struct HdfSBufImpl * impl,uint32_t size)84 static bool SbufRawImplReadRollback(struct HdfSBufImpl *impl, uint32_t size)
85 {
86 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
87 size_t alignSize;
88 if (sbuf == NULL) {
89 return false;
90 }
91
92 alignSize = SbufRawImplGetAlignSize(size);
93 if (sbuf->readPos < alignSize) {
94 return false;
95 }
96
97 sbuf->readPos -= alignSize;
98 return true;
99 }
100
SbufRawImplGetData(const struct HdfSBufImpl * impl)101 static const uint8_t *SbufRawImplGetData(const struct HdfSBufImpl *impl)
102 {
103 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
104 if (sbuf == NULL) {
105 HDF_LOGE("The obtained data is null, and the input Sbuf is null.");
106 return NULL;
107 }
108 return (uint8_t *)sbuf->data;
109 }
110
SbufRawImplSetDataSize(struct HdfSBufImpl * impl,size_t size)111 static void SbufRawImplSetDataSize(struct HdfSBufImpl *impl, size_t size)
112 {
113 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
114 if (sbuf == NULL) {
115 return;
116 }
117 if (size <= sbuf->capacity) {
118 sbuf->readPos = 0;
119 sbuf->writePos = size;
120 }
121 }
122
SbufRawImplFlush(struct HdfSBufImpl * impl)123 static void SbufRawImplFlush(struct HdfSBufImpl *impl)
124 {
125 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
126 if (sbuf != NULL) {
127 sbuf->readPos = 0;
128 sbuf->writePos = 0;
129 }
130 }
131
SbufRawImplGetCapacity(const struct HdfSBufImpl * impl)132 static size_t SbufRawImplGetCapacity(const struct HdfSBufImpl *impl)
133 {
134 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
135 return (sbuf != NULL) ? sbuf->capacity : 0;
136 }
137
SbufRawImplGetDataSize(const struct HdfSBufImpl * impl)138 static size_t SbufRawImplGetDataSize(const struct HdfSBufImpl *impl)
139 {
140 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
141 return (sbuf != NULL) ? sbuf->writePos : 0;
142 }
143
SbufRawImplGrow(struct HdfSBufRaw * sbuf,uint32_t growSize)144 static bool SbufRawImplGrow(struct HdfSBufRaw *sbuf, uint32_t growSize)
145 {
146 uint32_t newSize;
147 uint8_t *newData = NULL;
148 if (sbuf->isBind) {
149 HDF_LOGE("%s: binded sbuf oom", __func__);
150 return false;
151 }
152
153 newSize = SbufRawImplGetAlignSize(sbuf->capacity + growSize);
154 if (newSize < sbuf->capacity) {
155 HDF_LOGE("%s: grow size overflow", __func__);
156 return false;
157 }
158 if (newSize > HDF_SBUF_MAX_SIZE) {
159 HDF_LOGE("%s: buf size over limit", __func__);
160 return false;
161 }
162
163 newData = OsalMemCalloc(newSize);
164 if (newData == NULL) {
165 HDF_LOGE("%s: oom", __func__);
166 return false;
167 }
168
169 if (sbuf->data != NULL) {
170 if (memcpy_s(newData, newSize, sbuf->data, sbuf->writePos) != EOK) {
171 OsalMemFree(newData);
172 return false;
173 }
174 OsalMemFree(sbuf->data);
175 }
176
177 sbuf->data = newData;
178 sbuf->capacity = newSize;
179
180 return true;
181 }
182
SbufRawImplWrite(struct HdfSBufImpl * impl,const uint8_t * data,uint32_t size)183 static bool SbufRawImplWrite(struct HdfSBufImpl *impl, const uint8_t *data, uint32_t size)
184 {
185 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
186 size_t alignSize;
187 size_t writeableSize;
188 uint8_t *dest = NULL;
189
190 if (sbuf == NULL || sbuf->data == NULL || data == NULL) {
191 return false;
192 }
193
194 if (size == 0) {
195 return true;
196 }
197
198 alignSize = SbufRawImplGetAlignSize(size);
199 // in case of desireCapacity overflow
200 if (alignSize < size) {
201 HDF_LOGE("desireCapacity overflow");
202 return false;
203 }
204 writeableSize = SbufRawImplGetLeftWriteSize(sbuf);
205 if (alignSize > writeableSize) {
206 size_t growSize = (alignSize > HDF_SBUF_GROW_SIZE_DEFAULT) ? (alignSize + HDF_SBUF_GROW_SIZE_DEFAULT)
207 : HDF_SBUF_GROW_SIZE_DEFAULT;
208 if (!SbufRawImplGrow(sbuf, growSize)) {
209 return false;
210 }
211 writeableSize = SbufRawImplGetLeftWriteSize(sbuf);
212 }
213
214 dest = sbuf->data + sbuf->writePos;
215 if (memcpy_s(dest, writeableSize, data, size) != EOK) {
216 return false; /* never hits */
217 }
218
219 sbuf->writePos += alignSize;
220 return true;
221 }
222
SbufRawImplRead(struct HdfSBufImpl * impl,uint8_t * data,uint32_t readSize)223 static bool SbufRawImplRead(struct HdfSBufImpl *impl, uint8_t *data, uint32_t readSize)
224 {
225 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
226 size_t alignSize;
227 if (sbuf == NULL || sbuf->data == NULL || data == NULL) {
228 return false;
229 }
230
231 if (readSize == 0) {
232 return true;
233 }
234
235 alignSize = SbufRawImplGetAlignSize(readSize);
236 if (alignSize > SbufRawImplGetLeftReadSize(sbuf)) {
237 HDF_LOGE("Read out of buffer range");
238 return false;
239 }
240
241 if (memcpy_s(data, readSize, sbuf->data + sbuf->readPos, readSize) != EOK) {
242 return false; // never hit
243 }
244 sbuf->readPos += alignSize;
245 return true;
246 }
247
SbufRawImplWriteUint64(struct HdfSBufImpl * impl,uint64_t value)248 static bool SbufRawImplWriteUint64(struct HdfSBufImpl *impl, uint64_t value)
249 {
250 return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value));
251 }
252
SbufRawImplWriteUint32(struct HdfSBufImpl * impl,uint32_t value)253 static bool SbufRawImplWriteUint32(struct HdfSBufImpl *impl, uint32_t value)
254 {
255 return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value));
256 }
257
SbufRawImplWriteUint16(struct HdfSBufImpl * impl,uint16_t value)258 static bool SbufRawImplWriteUint16(struct HdfSBufImpl *impl, uint16_t value)
259 {
260 return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value));
261 }
262
SbufRawImplWriteUint8(struct HdfSBufImpl * impl,uint8_t value)263 static bool SbufRawImplWriteUint8(struct HdfSBufImpl *impl, uint8_t value)
264 {
265 return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value));
266 }
267
SbufRawImplWriteInt64(struct HdfSBufImpl * impl,int64_t value)268 static bool SbufRawImplWriteInt64(struct HdfSBufImpl *impl, int64_t value)
269 {
270 return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value));
271 }
272
SbufRawImplWriteInt32(struct HdfSBufImpl * impl,int32_t value)273 static bool SbufRawImplWriteInt32(struct HdfSBufImpl *impl, int32_t value)
274 {
275 return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value));
276 }
277
SbufRawImplWriteInt16(struct HdfSBufImpl * impl,int16_t value)278 static bool SbufRawImplWriteInt16(struct HdfSBufImpl *impl, int16_t value)
279 {
280 return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value));
281 }
282
SbufRawImplWriteInt8(struct HdfSBufImpl * impl,int8_t value)283 static bool SbufRawImplWriteInt8(struct HdfSBufImpl *impl, int8_t value)
284 {
285 return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value));
286 }
287
SbufRawImplWriteBuffer(struct HdfSBufImpl * impl,const uint8_t * data,uint32_t writeSize)288 static bool SbufRawImplWriteBuffer(struct HdfSBufImpl *impl, const uint8_t *data, uint32_t writeSize)
289 {
290 if (impl == NULL) {
291 HDF_LOGE("Failed to write the Sbuf, invalid input params");
292 return false;
293 }
294 if (data == NULL) {
295 return SbufRawImplWriteInt32(impl, 0);
296 }
297
298 if (!SbufRawImplWriteInt32(impl, writeSize)) {
299 return false;
300 }
301 if (!SbufRawImplWrite(impl, data, writeSize)) {
302 (void)SbufRawImplWriteRollback(impl, sizeof(int32_t));
303 return false;
304 }
305
306 return true;
307 }
308
SbufRawImplWriteString(struct HdfSBufImpl * impl,const char * value)309 static bool SbufRawImplWriteString(struct HdfSBufImpl *impl, const char *value)
310 {
311 if (impl == NULL) {
312 HDF_LOGE("%s: input null", __func__);
313 return false;
314 }
315
316 return SbufRawImplWriteBuffer(impl, (const uint8_t *)value, value ? (strlen(value) + 1) : 0);
317 }
318
SbufRawImplReadUint64(struct HdfSBufImpl * impl,uint64_t * value)319 static bool SbufRawImplReadUint64(struct HdfSBufImpl *impl, uint64_t *value)
320 {
321 return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value));
322 }
323
SbufRawImplReadUint32(struct HdfSBufImpl * impl,uint32_t * value)324 static bool SbufRawImplReadUint32(struct HdfSBufImpl *impl, uint32_t *value)
325 {
326 return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value));
327 }
328
SbufRawImplReadUint16(struct HdfSBufImpl * impl,uint16_t * value)329 static bool SbufRawImplReadUint16(struct HdfSBufImpl *impl, uint16_t *value)
330 {
331 return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value));
332 }
333
SbufRawImplReadUint8(struct HdfSBufImpl * impl,uint8_t * value)334 static bool SbufRawImplReadUint8(struct HdfSBufImpl *impl, uint8_t *value)
335 {
336 return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value));
337 }
338
SbufRawImplReadInt64(struct HdfSBufImpl * impl,int64_t * value)339 static bool SbufRawImplReadInt64(struct HdfSBufImpl *impl, int64_t *value)
340 {
341 return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value));
342 }
343
SbufRawImplReadInt32(struct HdfSBufImpl * impl,int32_t * value)344 static bool SbufRawImplReadInt32(struct HdfSBufImpl *impl, int32_t *value)
345 {
346 return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value));
347 }
348
SbufRawImplReadInt16(struct HdfSBufImpl * impl,int16_t * value)349 static bool SbufRawImplReadInt16(struct HdfSBufImpl *impl, int16_t *value)
350 {
351 return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value));
352 }
353
SbufRawImplReadInt8(struct HdfSBufImpl * impl,int8_t * value)354 static bool SbufRawImplReadInt8(struct HdfSBufImpl *impl, int8_t *value)
355 {
356 return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value));
357 }
358
SbufRawImplReadBuffer(struct HdfSBufImpl * impl,const uint8_t ** data,uint32_t * readSize)359 static bool SbufRawImplReadBuffer(struct HdfSBufImpl *impl, const uint8_t **data, uint32_t *readSize)
360 {
361 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
362 int buffSize = 0;
363 size_t alignSize;
364 if (sbuf == NULL || sbuf->data == NULL || data == NULL || readSize == NULL) {
365 HDF_LOGE("%s: input invalid", __func__);
366 return false;
367 }
368
369 if (!SbufRawImplReadInt32(impl, &buffSize)) {
370 return false;
371 }
372
373 if (buffSize == 0) {
374 *data = NULL;
375 *readSize = 0;
376 return true;
377 }
378 alignSize = SbufRawImplGetAlignSize(buffSize);
379 if (alignSize > SbufRawImplGetLeftReadSize(sbuf)) {
380 HDF_LOGE("%s:readBuff out of range", __func__);
381 (void)SbufRawImplReadRollback(impl, sizeof(int32_t));
382 return false;
383 }
384
385 *data = sbuf->data + sbuf->readPos;
386 *readSize = buffSize;
387 sbuf->readPos += alignSize;
388 return true;
389 }
390
SbufRawImplReadString(struct HdfSBufImpl * impl)391 static const char *SbufRawImplReadString(struct HdfSBufImpl *impl)
392 {
393 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
394 int32_t strLen = 0;
395 size_t alignSize;
396 char *str = NULL;
397 if (sbuf == NULL || sbuf->data == NULL) {
398 HDF_LOGE("%s: input null", __func__);
399 return NULL;
400 }
401 /* This length contains the '\0' at the end of the string. */
402 if (!SbufRawImplReadInt32(impl, &strLen) || strLen <= 0) {
403 return NULL;
404 }
405 alignSize = SbufRawImplGetAlignSize(strLen);
406 if (strLen > INT16_MAX || alignSize > SbufRawImplGetLeftReadSize(sbuf)) {
407 (void)SbufRawImplReadRollback(impl, sizeof(int32_t));
408 return NULL;
409 }
410
411 str = (char *)(sbuf->data + sbuf->readPos);
412 sbuf->readPos += alignSize;
413 /* Set '\0' at end of the string forcibly. */
414 str[strLen - 1] = '\0';
415 return str;
416 }
417
SbufRawImplCopy(const struct HdfSBufImpl * impl)418 static struct HdfSBufImpl *SbufRawImplCopy(const struct HdfSBufImpl *impl)
419 {
420 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
421 struct HdfSBufRaw *new = NULL;
422 if (sbuf == NULL || sbuf->data == NULL) {
423 return NULL;
424 }
425
426 new = SbufRawImplNewInstance(sbuf->capacity);
427 if (new == NULL) {
428 return NULL;
429 }
430 new->capacity = sbuf->capacity;
431 new->readPos = 0;
432 new->writePos = sbuf->writePos;
433 if (memcpy_s(new->data, new->capacity, sbuf->data, sbuf->capacity) != EOK) {
434 SbufRawImplRecycle(&new->infImpl);
435 return NULL;
436 }
437
438 return &new->infImpl;
439 }
440
SbufRawImplMove(struct HdfSBufImpl * impl)441 static struct HdfSBufImpl *SbufRawImplMove(struct HdfSBufImpl *impl)
442 {
443 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
444 struct HdfSBufRaw *new = NULL;
445 if (sbuf == NULL || sbuf->isBind) {
446 return NULL;
447 }
448
449 new = OsalMemCalloc(sizeof(struct HdfSBufRaw));
450 if (new == NULL) {
451 return NULL;
452 }
453 new->capacity = sbuf->capacity;
454 new->readPos = 0;
455 new->writePos = sbuf->writePos;
456 new->data = sbuf->data;
457
458 sbuf->data = NULL;
459 sbuf->capacity = 0;
460 SbufRawImplFlush(&sbuf->infImpl);
461 SbufInterfaceAssign(&new->infImpl);
462
463 return &new->infImpl;
464 }
465
SbufRawImplTransDataOwnership(struct HdfSBufImpl * impl)466 static void SbufRawImplTransDataOwnership(struct HdfSBufImpl *impl)
467 {
468 struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl);
469 if (sbuf == NULL) {
470 return;
471 }
472
473 sbuf->isBind = false;
474 }
475
SbufInterfaceAssign(struct HdfSBufImpl * inf)476 static void SbufInterfaceAssign(struct HdfSBufImpl *inf)
477 {
478 inf->writeBuffer = SbufRawImplWriteBuffer;
479 inf->writeUint64 = SbufRawImplWriteUint64;
480 inf->writeUint32 = SbufRawImplWriteUint32;
481 inf->writeUint16 = SbufRawImplWriteUint16;
482 inf->writeUint8 = SbufRawImplWriteUint8;
483 inf->writeInt64 = SbufRawImplWriteInt64;
484 inf->writeInt32 = SbufRawImplWriteInt32;
485 inf->writeInt16 = SbufRawImplWriteInt16;
486 inf->writeInt8 = SbufRawImplWriteInt8;
487 inf->writeString = SbufRawImplWriteString;
488 inf->readBuffer = SbufRawImplReadBuffer;
489 inf->readUint64 = SbufRawImplReadUint64;
490 inf->readUint32 = SbufRawImplReadUint32;
491 inf->readUint16 = SbufRawImplReadUint16;
492 inf->readUint8 = SbufRawImplReadUint8;
493 inf->readInt64 = SbufRawImplReadInt64;
494 inf->readInt32 = SbufRawImplReadInt32;
495 inf->readInt16 = SbufRawImplReadInt16;
496 inf->readInt8 = SbufRawImplReadInt8;
497 inf->readString = SbufRawImplReadString;
498 inf->getData = SbufRawImplGetData;
499 inf->flush = SbufRawImplFlush;
500 inf->getCapacity = SbufRawImplGetCapacity;
501 inf->getDataSize = SbufRawImplGetDataSize;
502 inf->setDataSize = SbufRawImplSetDataSize;
503 inf->recycle = SbufRawImplRecycle;
504 inf->move = SbufRawImplMove;
505 inf->copy = SbufRawImplCopy;
506 inf->transDataOwnership = SbufRawImplTransDataOwnership;
507 }
508
SbufRawImplNewInstance(size_t capacity)509 static struct HdfSBufRaw *SbufRawImplNewInstance(size_t capacity)
510 {
511 struct HdfSBufRaw *sbuf = NULL;
512 if (capacity > HDF_SBUF_MAX_SIZE) {
513 HDF_LOGE("%s: Sbuf size exceeding max limit", __func__);
514 return NULL;
515 }
516 sbuf = (struct HdfSBufRaw *)OsalMemCalloc(sizeof(struct HdfSBufRaw));
517 if (sbuf == NULL) {
518 HDF_LOGE("Sbuf instance failure");
519 return NULL;
520 }
521
522 sbuf->data = (uint8_t *)OsalMemCalloc(capacity);
523 if (sbuf->data == NULL) {
524 OsalMemFree(sbuf);
525 HDF_LOGE("sbuf obtain memory oom, size=%u", (uint32_t)capacity);
526 return NULL;
527 }
528 sbuf->capacity = capacity;
529 sbuf->writePos = 0;
530 sbuf->readPos = 0;
531 sbuf->isBind = false;
532 SbufInterfaceAssign(&sbuf->infImpl);
533 return sbuf;
534 }
535
SbufObtainRaw(size_t capacity)536 struct HdfSBufImpl *SbufObtainRaw(size_t capacity)
537 {
538 struct HdfSBufRaw *sbuf = SbufRawImplNewInstance(capacity);
539 if (sbuf == NULL) {
540 return NULL;
541 }
542 return &sbuf->infImpl;
543 }
544
SbufBindRaw(uintptr_t base,size_t size)545 struct HdfSBufImpl *SbufBindRaw(uintptr_t base, size_t size)
546 {
547 struct HdfSBufRaw *sbuf = NULL;
548 if (base == 0 || size == 0) {
549 return NULL;
550 }
551 /* 4-byte alignment is required for base. */
552 if ((base & 0x3) != 0) {
553 HDF_LOGE("Base not in 4-byte alignment");
554 return NULL;
555 }
556 sbuf = (struct HdfSBufRaw *)OsalMemAlloc(sizeof(struct HdfSBufRaw));
557 if (sbuf == NULL) {
558 HDF_LOGE("%s: oom", __func__);
559 return NULL;
560 }
561
562 sbuf->data = (uint8_t *)base;
563 sbuf->capacity = size;
564 sbuf->writePos = size;
565 sbuf->readPos = 0;
566 sbuf->isBind = true;
567 SbufInterfaceAssign(&sbuf->infImpl);
568 return &sbuf->infImpl;
569 }