static int bsd_number( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; CHECK_LENGTH( 1); uint8_t opcode = buffer[0]; CHECK_DECODE( decodeInteger( ctx, x, buffer, length, &BS_NUMBER_INTEGER)); /* Only go on if integer decoding failed */ switch( opcode) { case BS_N_NULL: decodeNull( ctx, x); break; case BS_N_FLOAT32: CHECK_LENGTH( 5); x->kind = BSD_DOUBLE; float f; memcpy( &f, buffer + 1, sizeof(float)); ntoh( &f, sizeof(float), sendian.float_); x->content.d = f; break; case BS_N_FLOAT64: CHECK_LENGTH( 9); x->kind = BSD_DOUBLE; memcpy( &(x->content.d), buffer + 1, sizeof(double)); ntoh( &(x->content.d), sizeof(double), sendian.double_); break; default: return bsd_error( x, BSD_EINVALID); } return nread; }
static int bsd_uis( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; CHECK_LENGTH( 1); uint8_t opcode = buffer[0]; CHECK_DECODE( decodeString( ctx, x, buffer, length, &BS_UIS_STRING)); x->kind = BSD_INT; if( 0x3b <= opcode && opcode <= 0xc6) { /* Tiny unsigned */ x->content.i = opcode - 0x3b; } else if( 0xc7 <= opcode && opcode <= 0xe6) { /* Small unsigned */ CHECK_LENGTH( 2); x->content.i = ((opcode - 0xc7) << 8) + buffer[1] + BS_UTI_MAX + 1; } else if( 0xe7 <= opcode && opcode <= 0xf6) { /* Medium unsigned */ CHECK_LENGTH( 3); x->content.i = ((opcode - 0xe7) << 16) + (buffer[1] << 8) + buffer[2] + BS_USI_MAX + 1; } else if( 0xf7 <= opcode && opcode <= 0xfe) { /* Large unsigned */ CHECK_LENGTH( 4); x->content.i = ((opcode - 0xf7) << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3] + BS_UMI_MAX + 1; } else if( 0xff == opcode) { /* XLarge unsigned */ CHECK_LENGTH( 5); x->content.i = ((uint32_t)buffer[1] << 24) + ((uint32_t)buffer[2] << 16) + ((uint32_t)buffer[3] << 8) + (uint32_t)buffer[4]; } else if( 0x00 == opcode) { decodeNull( ctx, x); } else { return bsd_error( x, BSD_EINVALID); } return nread; }
/* * FUNCTION UTL_FILE.PUTF(file UTL_FILE.FILE_TYPE, * format text, * arg1 text, * arg2 text, * arg3 text, * arg4 text, * arg5 text) * RETURNS bool; * * Puts formated data to file. Allows %s like subst symbol. * * Exception: * INVALID_FILEHANDLE, INVALID_OPERATION, WRITE_ERROR */ Datum utl_file_putf(PG_FUNCTION_ARGS) { FILE *f; char *format; int max_linesize = 0; int encoding = 0; int format_length; char *fpt; int cur_par = 0; int cur_len = 0; CHECK_FILE_HANDLE(); f = get_stream(PG_GETARG_INT32(0), &max_linesize, &encoding); NOT_NULL_ARG(1); format = encode_text(encoding, PG_GETARG_TEXT_P(1), &format_length); for (fpt = format; format_length > 0; fpt++, format_length--) { if (format_length == 1) { /* last char */ CHECK_LENGTH(++cur_len); if (fputc(*fpt, f) == EOF) CHECK_ERRNO_PUT(); continue; } /* ansi compatible string */ if (fpt[0] == '\\' && fpt[1] == 'n') { CHECK_LENGTH(++cur_len); if (fputc('\n', f) == EOF) CHECK_ERRNO_PUT(); fpt++; format_length--; continue; } if (fpt[0] == '%') { if (fpt[1] == '%') { CHECK_LENGTH(++cur_len); if (fputc('%', f) == EOF) CHECK_ERRNO_PUT(); } else if (fpt[1] == 's' && ++cur_par <= 5 && !PG_ARGISNULL(cur_par + 1)) { cur_len += do_write(fcinfo, cur_par + 1, f, max_linesize - cur_len, encoding); } fpt++; format_length--; continue; } CHECK_LENGTH(++cur_len); if (fputc(fpt[0], f) == EOF) CHECK_ERRNO_PUT(); } PG_RETURN_BOOL(true); }
static int bsd_global( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; CHECK_LENGTH( 1); uint8_t opcode = buffer[0]; CHECK_DECODE( decodeInteger( ctx, x, buffer, length, &BS_GLOBAL_INTEGER)); CHECK_DECODE( decodeString( ctx, x, buffer, length, &BS_GLOBAL_STRING)); CHECK_DECODE( decodeCollection( ctx, x, buffer, length, NULL, &BS_GLOBAL_LIST)); CHECK_DECODE( decodeCollection( ctx, x, buffer, length, NULL, &BS_GLOBAL_MAP)); CHECK_DECODE( decodeClass( ctx, x, buffer, length)); if( 0x60 <= opcode && opcode <= 0x6f) { /* object (short form) */ CHECK_ERROR( bsd_object( ctx, x, opcode - 0x60)); return nread; } switch( opcode) { case BS_G_NULL: /* null */ decodeNull( ctx, x); break; case 0x01: /* boolean true */ x->kind = BSD_BOOL; x->content.boolean = 1; break; case 0x02: /* boolean false */ x->kind = BSD_BOOL; x->content.boolean = 0; break; case 0x70: /* object (long form) */ CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + nread, length - nread), BSD_INT); CHECK_ERROR( bsd_object( ctx, x, x->content.i + 0x10)); break; case BS_G_FLOAT32: /* float */ CHECK_LENGTH( 5); x->kind = BSD_DOUBLE; float f; memcpy( &f, buffer + 1, sizeof(float)); ntoh( &f, sizeof(float), sendian.float_); x->content.d = f; break; case BS_G_FLOAT64: /* double */ CHECK_LENGTH( 9); x->kind = BSD_DOUBLE; memcpy( &(x->content.d), buffer + 1, sizeof(double)); ntoh( &(x->content.d), sizeof(double), sendian.double_); break; default: return bsd_error( x, BSD_EINVALID); } return nread; }
static int decodeCollection( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length, union bsd_stackframecontent_t **f, const bs_coll_encoding_t *enc) { int nread = 0; uint8_t opcode = buffer[0]; CHECK_LENGTH( 1); if( enc->empty_opcode == opcode) { /* empty container */ x->kind = bsd_typeFromFrameKind( enc->fixed_kind); x->content.length = 0; CHECK_ERROR( openContainer( ctx, enc->fixed_kind, BS_CTXID_GLOBAL, 0, f)); } else if( enc->small_untyped_opcode <= opcode && opcode <= enc->small_untyped_opcode + enc->small_limit - 1) { /* Small untyped container */ x->kind = bsd_typeFromFrameKind( enc->fixed_kind); x->content.length = opcode - enc->small_untyped_opcode + 1; CHECK_ERROR( openContainer( ctx, enc->fixed_kind, BS_CTXID_GLOBAL, x->content.length, f)); } else if( enc->long_untyped_opcode == opcode) { /* Long untyped container */ CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + 1, length + 1), BSD_INT); x->kind = bsd_typeFromFrameKind( enc->fixed_kind); x->content.length = x->content.i + enc->small_limit + 1; CHECK_ERROR( openContainer( ctx, enc->fixed_kind, BS_CTXID_GLOBAL, x->content.length, f)); } else if( enc->variable_untyped_opcode == opcode) { /* Variable untyped container */ x->kind = bsd_typeFromFrameKind( enc->variable_kind); CHECK_ERROR( openContainer( ctx, enc->variable_kind, BS_CTXID_GLOBAL, -1, f)); } else if( enc->small_typed_opcode <= opcode && opcode <= enc->small_typed_opcode + enc->small_limit - 1) { /* Small typed container */ CHECK_LENGTH( 2); x->kind = bsd_typeFromFrameKind( enc->fixed_kind); x->content.length = opcode - enc->small_typed_opcode + 1; CHECK_ERROR( openContainer( ctx, enc->fixed_kind, buffer[1], x->content.length, f)); } else if( enc->long_typed_opcode == opcode) { /* Long typed container */ CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + 1, length + 1), BSD_INT); CHECK_LENGTH( nread + 1); x->kind = bsd_typeFromFrameKind( enc->fixed_kind); x->content.length = x->content.i + enc->small_limit + 1; CHECK_ERROR( openContainer( ctx, enc->fixed_kind, buffer[nread-1], x->content.length, f)); } else if( enc->variable_typed_opcode == opcode) { /* Variable untyped container */ CHECK_LENGTH( 2); x->kind = bsd_typeFromFrameKind( enc->variable_kind); CHECK_ERROR( openContainer( ctx, enc->variable_kind, buffer[1], -1, f)); } else { return 0; } return nread; }
void fill_icmp6types(ipfw_insn_icmp6 *cmd, char *av, int cblen) { uint8_t type; CHECK_LENGTH(cblen, F_INSN_SIZE(ipfw_insn_icmp6)); bzero(cmd, sizeof(*cmd)); while (*av) { if (*av == ',') av++; type = strtoul(av, &av, 0); if (*av != ',' && *av != '\0') errx(EX_DATAERR, "invalid ICMP6 type"); /* * XXX: shouldn't this be 0xFF? I can't see any reason why * we shouldn't be able to filter all possiable values * regardless of the ability of the rest of the kernel to do * anything useful with them. */ if (type > ICMP6_MAXTYPE) errx(EX_DATAERR, "ICMP6 type out of range"); cmd->d[type / 32] |= ( 1 << (type % 32)); } cmd->o.opcode = O_ICMP6TYPE; cmd->o.len |= F_INSN_SIZE(ipfw_insn_icmp6); }
/** * Try to decode a number under given context. * This algorithm assume that all number kind are consecutive and in the same order. */ static int decodeInteger( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length, const bs_integer_encoding_t *enc) { int nread = 0; uint8_t opcode = buffer[0]; CHECK_LENGTH( 1); x->kind = BSD_INT; if( (enc->tiny_zero_opcode + enc->tiny_min) <= opcode && opcode <= (enc->tiny_zero_opcode + enc->tiny_max)) { /* tiny number */ x->content.i = opcode - enc->tiny_zero_opcode; } else if( enc->small_pos_opcode <= opcode && opcode < enc->small_neg_opcode) { /* small positive number */ CHECK_LENGTH( 2); x->content.i = ((opcode - enc->small_pos_opcode) << 8) + buffer[1] + enc->tiny_max + 1; } else if( enc->small_neg_opcode <= opcode && opcode < enc->medium_pos_opcode) { /* small negative number */ CHECK_LENGTH( 2); x->content.i = -(((opcode - enc->small_neg_opcode) << 8) + buffer[1]) + enc->tiny_min - 1; } else if( enc->medium_pos_opcode <= opcode && opcode < enc->medium_neg_opcode) { /* medium positive number */ CHECK_LENGTH( 3); x->content.i = ((opcode - enc->medium_pos_opcode) << 16) + (buffer[1] << 8) + buffer[2] + enc->small_max + 1; } else if( enc->medium_neg_opcode <= opcode && opcode < enc->large_pos_opcode) { /* medium negative number */ CHECK_LENGTH( 3); x->content.i = -(((opcode - enc->medium_neg_opcode) << 16) + (buffer[1] << 8) + buffer[2]) + enc->small_min - 1; } else if( enc->large_pos_opcode <= opcode && opcode < enc->large_neg_opcode) { /* large positive opcode */ CHECK_LENGTH( 4); x->content.i = ((opcode - enc->large_pos_opcode) << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3] + enc->medium_max + 1; } else if( enc->large_neg_opcode <= opcode && opcode <= enc->last_large_neg_opcode) { /* large negative opcode */ CHECK_LENGTH( 4); x->content.i = -(((opcode - enc->large_neg_opcode) << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]) + enc->medium_min - 1; } else if( enc->int32_opcode == opcode) { /* big endian 32 bits integer */ CHECK_LENGTH( 5); int32_t val; memcpy( &val, buffer + 1, sizeof(int32_t)); ntoh( &val, sizeof(int32_t), sendian.int32_); x->content.i = val; } else if( enc->int64_opcode == opcode) { /* big endian 64 bits integer */ CHECK_LENGTH( 9); memcpy( &(x->content.i), buffer + 1, sizeof(int64_t)); ntoh( &(x->content.i), sizeof(int64_t), sendian.int64_); } else { return 0; } return nread; }
static int bsd_chunked( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; CHECK_LENGTH( 2); size_t chunksize = (buffer[0] << 8) + buffer[1]; if( 0 == chunksize) { x->kind = BSD_CLOSE; x->content.cont_type = BSD_CHUNKED_STRING; ctx->stacksize--; } else { CHECK_LENGTH( chunksize + 2); x->kind = BSD_CHUNK; x->content.chunk.data = (const char *) buffer + 2; x->content.chunk.length = chunksize; } return nread; }
static int bsd_int32( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; union { uint32_t u; int32_t i; } val; CHECK_LENGTH( 4); val.u = ((uint32_t)buffer[0] << 24) + ((uint32_t)buffer[1] << 16) + ((uint32_t)buffer[2] << 8) + (uint32_t)buffer[3]; x->kind = BSD_INT; x->content.i = val.i; // check for escape sequence if( 0x80000000U == val.u) { CHECK_LENGTH( 5); switch( buffer[4]) { case 0x00: decodeNull( ctx, x); break; case 0x01: break; default: return bsd_error( x, BSD_EINVALID); } } return nread; }
static int decodeString( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length, const bs_string_encoding_t *enc) { int nread = 0; uint8_t opcode = buffer[0]; CHECK_LENGTH( 1); x->kind = BSD_STRING; if( enc->small_opcode <= opcode && opcode < enc->medium_opcode) { /* Small string */ size_t len = opcode - enc->small_opcode; CHECK_LENGTH( len + 1); bsd_string( x, len, (const char *) buffer + 1); } else if( enc->medium_opcode <= opcode && opcode < enc->large_opcode) { /* Medium string */ CHECK_LENGTH( 2); size_t len = ((opcode - enc->medium_opcode) << 8) + buffer[1] + enc->small_limit + 1; CHECK_LENGTH( len + 2); bsd_string( x, len, (const char *) buffer + 2); } else if( enc->large_opcode == opcode) { /* Large string */ CHECK_LENGTH( 3); size_t len = ((buffer[1]) << 8) + buffer[2] + enc->medium_limit + 1; CHECK_LENGTH( len + 3); bsd_string( x, len, (const char *) buffer + 3); } else if( enc->chunked_opcode == opcode) { CHECK_ERROR( openContainer( ctx, BS_FCHUNKED, BS_CTXID_CHUNKED, -1, NULL)); x->kind = BSD_CHUNKED_STRING; } else { return 0; } return nread; }
size_t utf16_to_utf8(char *dst, size_t dst_len, const uint16_t *src, size_t src_len, int flags, int *errp) { uint8_t spos, dpos; int error; #define CHECK_LENGTH(l) (dpos > dst_len-(l) ? dst=NULL : NULL) #define ADD_BYTE(b) (dst ? dst[dpos] = (b) : 0, dpos++) error = 0; dpos = 0; for (spos = 0; spos < src_len; spos++) { if (src[spos] < 0x80) { CHECK_LENGTH(1); ADD_BYTE(src[spos]); } else if (src[spos] < 0x800) { CHECK_LENGTH(2); ADD_BYTE(0xc0 | (src[spos]>>6)); ADD_BYTE(0x80 | (src[spos] & 0x3f)); } else if ((src[spos] & 0xdc00) == 0xd800) {
static int bsd_double( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; union { uint64_t u; double d; } val; CHECK_LENGTH( 8); memcpy( &val.d, buffer, sizeof(double)); ntoh( &val.d, sizeof(double), sendian.float_); x->content.d = val.d; x->kind = BSD_DOUBLE; // check for escape sequence if( 0xFFFFFFFFFFFFFFFFULL == val.u) { CHECK_LENGTH( 9); switch( buffer[8]) { case 0x00: decodeNull( ctx, x); break; case 0x01: break; default: return bsd_error( x, BSD_EINVALID); } } return nread; }
static int bsd_float( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; union { uint32_t u; float f; } val; CHECK_LENGTH( 4); memcpy( &val.f, buffer, sizeof(float)); ntoh( &val.f, sizeof(float), sendian.float_); x->content.d = val.f; x->kind = BSD_DOUBLE; // check for escape sequence if( 0xFFFFFFFFU == val.u) { CHECK_LENGTH( 5); switch( buffer[4]) { case 0x00: decodeNull( ctx, x); break; case 0x01: break; default: return bsd_error( x, BSD_EINVALID); } } return nread; }
static int bsd_listmap( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; CHECK_LENGTH( 1); uint8_t opcode = buffer[0]; CHECK_DECODE( decodeCollection( ctx, x, buffer, length, NULL, &BS_LISTMAP_LIST)); CHECK_DECODE( decodeCollection( ctx, x, buffer, length, NULL, &BS_LISTMAP_MAP)); if( 0x00 == opcode) { decodeNull( ctx, x); } else { return bsd_error( x, BSD_EINVALID); } return nread; }
/* fwrite(encode(args[n], encoding), f) */ static int do_write(PG_FUNCTION_ARGS, int n, FILE *f, int max_linesize, int encoding) { text *arg = PG_GETARG_TEXT_P(n); char *str; int len; str = encode_text(encoding, arg, &len); CHECK_LENGTH(len); if (fwrite(str, 1, len, f) != len) CHECK_ERRNO_PUT(); if (VARDATA(arg) != str) pfree(str); PG_FREE_IF_COPY(arg, n); return len; }
static int decodeClass( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread, i, named, fieldnread; size_t nfields, blocksize, namesize; bs_classid_t classid; const char *name; const uint8_t *fieldbuffer; void *endofclass; bs_class_t *classdef; CHECK_LENGTH( 1); switch( buffer[0]) { case 0x71: named = 1; break; case 0x72: named = 0; name = NULL; namesize = 0; break; default: return 0; } // decoding is done in two passes: 1st to compute the size and allocate right amount of memory, // second one to make the actual data copy. blocksize = sizeof( bs_class_t); CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + nread, length - nread ), BSD_INT); classid = x->content.i; if( named) { CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + nread, length - nread ), BSD_STRING); name = x->content.string.data; namesize = x->content.string.length + 1; // add null terminator } CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + nread, length - nread), BSD_INT); nfields = x->content.i; // allocate class structure blocksize = sizeof( bs_class_t) + namesize + nfields * sizeof( struct bs_field_t); // 1st pass fieldbuffer = buffer; fieldnread = nread; for( i=0; i<nfields; i++) { if( named) { CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + nread, length - nread ), BSD_STRING); blocksize += x->content.length + 1; } CHECK_LENGTH( nread + 1); } // memory allocation classdef = BS_MEM_ALLOC( blocksize); if( NULL == classdef) return bsd_error( x, BSD_EMEMORY); classdef->classid = classid; classdef->nfields = nfields; classdef->mode = BS_CLASS_MANAGED; endofclass = ((void *)classdef) + sizeof( bs_class_t); classdef->classname = NULL; if( named) { memcpy( endofclass, name, namesize-1); ((char *)endofclass)[namesize-1] = '\0'; classdef->classname = endofclass; endofclass += namesize; } classdef->fields = endofclass; endofclass += nfields * sizeof( struct bs_field_t); // 2nd pass (no possible parsing errors since processing is the same as 1st pass) buffer = fieldbuffer; nread = fieldnread; for( i=0; i<classdef->nfields; i++) { if( named) { CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + nread, length - nread ), BSD_STRING); memcpy( endofclass, x->content.string.data, x->content.string.length); ((char *)endofclass)[x->content.string.length] = '\0'; classdef->fields[i].name = endofclass; endofclass += x->content.string.length + 1; } else { classdef->fields[i].name = NULL; } CHECK_LENGTH( nread + 1); classdef->fields[i].ctxid = buffer[nread - 1]; } bsd_addClass( ctx, classdef); x->kind = BSD_CLASSDEF; x->content.classdef = classdef; return nread; }