/* * Copyright (c) 2003-2012 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Serialization functions for strings. */ #include "cgi.h" /* Allocate and read a length-encoded string. */ char * SYS_ReadStringLen(int fd, size_t maxlen) { Uint32 len; char *s; if (SYS_ReadUint32v(fd, &len) == -1) { CGI_SetError("String length: %s", CGI_GetError()); goto fail; } if (len > (Uint32)maxlen) { CGI_SetError("String (%luB): Exceeds %luB limit", (Ulong)len, (Ulong)maxlen); goto fail; } if ((s = TryMalloc((size_t)len+1)) == NULL) { goto fail; } if (len > 0) { if (SYS_Read(fd, s, len) != 0) { CGI_SetError("String (%luB): %s", (Ulong)len, CGI_GetError()); Free(s); goto fail; } } s[len] = '\0'; return (s); fail: return (NULL); } /* * Read a length-encoded string (no exceptions) and return its contents * in newly-allocated memory. * * If s is non-NULL, *s is taken to be an existing, valid buffer which will * be reallocated to fit the new string size. */ int SYS_ReadStringLenv(int fd, size_t maxlen, char **s) { Uint32 len; char *sp; if (SYS_ReadUint32v(fd, &len) == -1) { CGI_SetError("String length: %s", CGI_GetError()); goto fail; } if (len > (Uint32)maxlen) { CGI_SetError("String (%luB): Exceeds %luB limit", (Ulong)len, (Ulong)maxlen); goto fail; } if ((sp = TryRealloc(*s, (size_t)len+1)) == NULL) { goto fail; } *s = sp; if (len > 0) { if (SYS_Read(fd, sp, len) != 0) { CGI_SetError("String (%luB): %s", (Ulong)len, CGI_GetError()); sp[0] = '\0'; goto fail; } sp[len] = '\0'; } return (0); fail: return (-1); } /* Write a length-encoded string. */ int SYS_WriteString(int fd, const char *s) { size_t len; if (s == NULL || s[0] == '\0') { SYS_WriteUint32(fd, 0); } else { len = strlen(s); SYS_WriteUint32(fd, (Uint32)len); if (SYS_Write(fd, s, len) != 0) return (-1); } return (0); } /* Write a length-encoded string. */ int SYS_WriteStringv(int fd, const char *s) { Uint32 len = (s != NULL && s[0] != '\0') ? strlen(s) : 0; if (SYS_WriteUint32v(fd, &len) == -1) { return (-1); } return (len > 0) ? SYS_Write(fd, s, len) : 0; } /* * Copy at most dst_size bytes from a length-encoded string to a fixed-size * buffer, returning 0 on success or -1 on failure. * The function NUL-terminates the string. */ int SYS_CopyString(char *dst, int fd, size_t dst_size) { Uint32 len; if (SYS_ReadUint32v(fd, &len) == -1) { CGI_SetError("String length: %s", CGI_GetError()); dst[0] = '\0'; return (-1); } if (len >= (Uint32)dst_size) { len = dst_size-1; } if (len == 0) { dst[0] = '\0'; } else { if (SYS_Read(fd, dst, (size_t)len) != 0) { dst[0] = '\0'; return (-1); } dst[len] = '\0'; } return (0); }