mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Moved cryptographic hashes to separate function crypt_hash(), crc32 - into function hash()
This commit is contained in:
parent
9900e56cbc
commit
e9f3eb360d
@ -361,18 +361,26 @@ Example:
|
||||
select cot(x) from y;
|
||||
|
||||
|
||||
-----
|
||||
CRC32
|
||||
-----
|
||||
----------
|
||||
CRYPT_HASH
|
||||
----------
|
||||
|
||||
Function:
|
||||
Returns CRC-32 with the polynomial 0x04C11DB7. Accepts argument of any type.
|
||||
Returns a cryptograpic hash of an argument using a specified algorithm.
|
||||
|
||||
Format:
|
||||
CRC32( <any value> )
|
||||
CRYPT_HASH( <any value> USING <algorithm> )
|
||||
|
||||
algorithm ::= { MD5 | SHA1 | SHA256 | SHA512 }
|
||||
|
||||
Important:
|
||||
- This function returns VARCHAR strings with OCTETS charset with length depended on algorithm.
|
||||
|
||||
- MD5 and SHA1 algorithms are not recommended for use due to known severe issues, that algorithms
|
||||
are provided ONLY for backward compatibility.
|
||||
|
||||
Example:
|
||||
select crc32(job_title) from job;
|
||||
select crypt_hash(x using sha256) from y;
|
||||
|
||||
|
||||
-------
|
||||
@ -560,21 +568,25 @@ HASH
|
||||
----
|
||||
|
||||
Function:
|
||||
Returns a HASH of a string using a specified algorithm.
|
||||
Returns a hash of an argument using a specified algorithm.
|
||||
|
||||
Format:
|
||||
HASH( <string> [ USING <algorithm> ] )
|
||||
HASH( <any value> [ USING <algorithm> ] )
|
||||
|
||||
algorithm ::= { MD5 | SHA1 | SHA256 | SHA512 }
|
||||
algorithm ::= { CRC32 }
|
||||
|
||||
Important:
|
||||
- The syntax without USING is very discouraged and maintained for backward compatibility.
|
||||
It returns a 64 bit integer and produces very bad hashes that easily result in collisions.
|
||||
- The syntax with USING is introduced in FB 4.0 and returns VARCHAR strings with OCTETS charset.
|
||||
|
||||
- The syntax with USING is introduced in FB 4.0 and returns an integer of appropriate size.
|
||||
|
||||
- Implemented in firebird CRC32 is using polynomial 0x04C11DB7.
|
||||
|
||||
Example:
|
||||
select hash(x) from y;
|
||||
select hash(x using sha256) from y;
|
||||
select hash(x using crc32) from y;
|
||||
|
||||
|
||||
|
||||
-----------------------------
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../common/classes/Hash.h"
|
||||
#include "../common/dsc.h"
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_X64) || defined(__x86_64__) || defined(__i386__)
|
||||
#ifdef _MSC_VER
|
||||
@ -126,8 +127,7 @@ void WeakHashContext::update(const void* data, FB_SIZE_T length)
|
||||
}
|
||||
}
|
||||
|
||||
void WeakHashContext::finish(Buffer& result)
|
||||
void WeakHashContext::finish(dsc& result)
|
||||
{
|
||||
UCHAR* resultBuffer = result.getBuffer(sizeof(hashNumber));
|
||||
memcpy(resultBuffer, &hashNumber, sizeof(hashNumber));
|
||||
result.makeInt64(0, &hashNumber);
|
||||
}
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
#include "../common/classes/array.h"
|
||||
|
||||
struct dsc;
|
||||
|
||||
namespace Firebird
|
||||
{
|
||||
template <typename K>
|
||||
@ -341,12 +343,8 @@ namespace Firebird
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class HashContext
|
||||
{
|
||||
public:
|
||||
typedef HalfStaticArray<UCHAR, 256> Buffer;
|
||||
|
||||
public:
|
||||
virtual ~HashContext()
|
||||
{
|
||||
@ -354,14 +352,14 @@ namespace Firebird
|
||||
|
||||
public:
|
||||
virtual void update(const void* data, FB_SIZE_T length) = 0;
|
||||
virtual void finish(Buffer& result) = 0;
|
||||
virtual void finish(dsc& result) = 0;
|
||||
};
|
||||
|
||||
class WeakHashContext FB_FINAL : public HashContext
|
||||
{
|
||||
public:
|
||||
virtual void update(const void* data, FB_SIZE_T length);
|
||||
virtual void finish(Buffer& result);
|
||||
virtual void finish(dsc& result);
|
||||
|
||||
private:
|
||||
SINT64 hashNumber = 0;
|
||||
@ -383,11 +381,12 @@ namespace Firebird
|
||||
|
||||
public:
|
||||
virtual void update(const void* data, FB_SIZE_T length);
|
||||
virtual void finish(Buffer& result);
|
||||
virtual void finish(dsc& result);
|
||||
|
||||
private:
|
||||
const Descriptor* descriptor;
|
||||
State* statePtr;
|
||||
UCharBuffer buffer;
|
||||
};
|
||||
|
||||
class Md5HashContext FB_FINAL : public LibTomCryptHashContext
|
||||
@ -413,6 +412,22 @@ namespace Firebird
|
||||
public:
|
||||
Sha512HashContext(MemoryPool& pool);
|
||||
};
|
||||
|
||||
class Crc32HashContext FB_FINAL : public HashContext
|
||||
{
|
||||
public:
|
||||
Crc32HashContext(MemoryPool& pool);
|
||||
~Crc32HashContext();
|
||||
|
||||
virtual void update(const void* data, FB_SIZE_T length);
|
||||
virtual void finish(dsc& result);
|
||||
|
||||
private:
|
||||
struct State;
|
||||
State* statePtr;
|
||||
SLONG hash;
|
||||
};
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
#endif // CLASSES_HASH_H
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../common/classes/Hash.h"
|
||||
#include "../common/dsc.h"
|
||||
#include "../intl/charsets.h"
|
||||
|
||||
#if !defined(__GNUC__) || defined(__clang__)
|
||||
#define LTC_NO_ASM // disable ASM in tomcrypt headers
|
||||
@ -45,9 +47,10 @@ struct LibTomCryptHashContext::State
|
||||
|
||||
|
||||
LibTomCryptHashContext::LibTomCryptHashContext(MemoryPool& pool, const Descriptor* aDescriptor)
|
||||
: descriptor(aDescriptor)
|
||||
: descriptor(aDescriptor),
|
||||
statePtr(FB_NEW_POOL(pool) State),
|
||||
buffer(pool)
|
||||
{
|
||||
statePtr = FB_NEW_POOL(pool) State();
|
||||
descriptor->tcDesc->init(&statePtr->tcState);
|
||||
}
|
||||
|
||||
@ -61,10 +64,11 @@ void LibTomCryptHashContext::update(const void* data, FB_SIZE_T length)
|
||||
descriptor->tcDesc->process(&statePtr->tcState, static_cast<const UCHAR*>(data), length);
|
||||
}
|
||||
|
||||
void LibTomCryptHashContext::finish(Buffer& result)
|
||||
void LibTomCryptHashContext::finish(dsc& result)
|
||||
{
|
||||
unsigned char* hashResult = result.getBuffer(descriptor->tcDesc->hashsize);
|
||||
unsigned char* hashResult = buffer.getBuffer(descriptor->tcDesc->hashsize);
|
||||
descriptor->tcDesc->done(&statePtr->tcState, hashResult);
|
||||
result.makeText(descriptor->tcDesc->hashsize, CS_BINARY, hashResult);
|
||||
}
|
||||
|
||||
|
||||
@ -98,3 +102,37 @@ Sha512HashContext::Sha512HashContext(MemoryPool& pool)
|
||||
: LibTomCryptHashContext(pool, &sha512Descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
struct Crc32HashContext::State
|
||||
{
|
||||
State()
|
||||
{
|
||||
crc32_init(&ctx);
|
||||
}
|
||||
|
||||
crc32_state ctx;
|
||||
};
|
||||
|
||||
|
||||
Crc32HashContext::Crc32HashContext(MemoryPool& pool)
|
||||
{
|
||||
statePtr = FB_NEW_POOL(pool) State();
|
||||
}
|
||||
|
||||
Crc32HashContext::~Crc32HashContext()
|
||||
{
|
||||
delete statePtr;
|
||||
}
|
||||
|
||||
void Crc32HashContext::update(const void* data, FB_SIZE_T length)
|
||||
{
|
||||
crc32_update(&statePtr->ctx, static_cast<const UCHAR*>(data), length);
|
||||
}
|
||||
|
||||
void Crc32HashContext::finish(dsc& result)
|
||||
{
|
||||
crc32_finish(&statePtr->ctx, &hash, sizeof hash);
|
||||
result.makeLong(0, &hash);
|
||||
}
|
||||
|
||||
|
@ -145,9 +145,9 @@ static const TOK tokens[] =
|
||||
{TOK_COUNTER, "COUNTER", true},
|
||||
{TOK_COVAR_POP, "COVAR_POP", false},
|
||||
{TOK_COVAR_SAMP, "COVAR_SAMP", false},
|
||||
{TOK_CRC32, "CRC32", true},
|
||||
{TOK_CREATE, "CREATE", false},
|
||||
{TOK_CROSS, "CROSS", false},
|
||||
{TOK_CRYPT_HASH, "CRYPT_HASH", true},
|
||||
{TOK_CSTRING, "CSTRING", true},
|
||||
{TOK_CTR_BIG_ENDIAN, "CTR_BIG_ENDIAN", true},
|
||||
{TOK_CTR_LENGTH, "CTR_LENGTH", true},
|
||||
|
@ -1 +1 @@
|
||||
60 shift/reduce conflicts, 17 reduce/reduce conflicts.
|
||||
61 shift/reduce conflicts, 17 reduce/reduce conflicts.
|
||||
|
@ -457,7 +457,6 @@ using namespace Firebird;
|
||||
%token <metaNamePtr> COS
|
||||
%token <metaNamePtr> COSH
|
||||
%token <metaNamePtr> COT
|
||||
%token <metaNamePtr> CRC32
|
||||
%token <metaNamePtr> DATEADD
|
||||
%token <metaNamePtr> DATEDIFF
|
||||
%token <metaNamePtr> DECODE
|
||||
@ -599,6 +598,7 @@ using namespace Firebird;
|
||||
%token <metaNamePtr> COMPARE_DECFLOAT
|
||||
%token <metaNamePtr> CONSISTENCY
|
||||
%token <metaNamePtr> COUNTER
|
||||
%token <metaNamePtr> CRYPT_HASH
|
||||
%token <metaNamePtr> CTR_BIG_ENDIAN
|
||||
%token <metaNamePtr> CTR_LENGTH
|
||||
%token <metaNamePtr> CTR_LITTLE_ENDIAN
|
||||
@ -8067,7 +8067,6 @@ system_function_std_syntax
|
||||
| COS
|
||||
| COSH
|
||||
| COT
|
||||
| CRC32
|
||||
| EXP
|
||||
| FLOOR
|
||||
| GEN_UUID
|
||||
@ -8152,7 +8151,7 @@ system_function_special_syntax
|
||||
}
|
||||
| HASH '(' value ')'
|
||||
{ $$ = newNode<SysFuncCallNode>(*$1, newNode<ValueListNode>($3)); }
|
||||
| HASH '(' value USING valid_symbol_name ')'
|
||||
| hash_func '(' value USING valid_symbol_name ')'
|
||||
{
|
||||
$$ = newNode<SysFuncCallNode>(*$1,
|
||||
newNode<ValueListNode>($3)->add(MAKE_str_constant(newIntlString($5->c_str()), CS_ASCII)));
|
||||
@ -8211,6 +8210,11 @@ system_function_special_syntax
|
||||
}
|
||||
;
|
||||
|
||||
%type <metaNamePtr> hash_func
|
||||
hash_func
|
||||
: HASH | CRYPT_HASH
|
||||
;
|
||||
|
||||
%type <metaNamePtr> rsa_encrypt_decrypt
|
||||
rsa_encrypt_decrypt
|
||||
: RSA_DECRYPT | RSA_ENCRYPT
|
||||
@ -8948,7 +8952,7 @@ non_reserved_word
|
||||
| COMPARE_DECFLOAT
|
||||
| CONNECTIONS
|
||||
| CONSISTENCY
|
||||
| CRC32
|
||||
| CRYPT_HASH
|
||||
| CTR_BIG_ENDIAN
|
||||
| CTR_LENGTH
|
||||
| CTR_LITTLE_ENDIAN
|
||||
|
@ -125,7 +125,7 @@ struct HashAlgorithmDescriptor
|
||||
USHORT length;
|
||||
HashContext* (*create)(MemoryPool&);
|
||||
|
||||
static const HashAlgorithmDescriptor* find(const char* name);
|
||||
static const HashAlgorithmDescriptor* find(const HashAlgorithmDescriptor** hashDescriptor, const MetaName name);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -149,21 +149,25 @@ struct HashAlgorithmDescriptorFactory
|
||||
|
||||
template <typename T> HashAlgorithmDescriptor HashAlgorithmDescriptorFactory<T>::desc;
|
||||
|
||||
static const HashAlgorithmDescriptor* hashAlgorithmDescriptors[] = {
|
||||
static const HashAlgorithmDescriptor* cryptHashAlgorithmDescriptors[] = {
|
||||
HashAlgorithmDescriptorFactory<Md5HashContext>::getInstance("MD5", 16),
|
||||
HashAlgorithmDescriptorFactory<Sha1HashContext>::getInstance("SHA1", 20),
|
||||
HashAlgorithmDescriptorFactory<Sha256HashContext>::getInstance("SHA256", 32),
|
||||
HashAlgorithmDescriptorFactory<Sha512HashContext>::getInstance("SHA512", 64)
|
||||
HashAlgorithmDescriptorFactory<Sha512HashContext>::getInstance("SHA512", 64),
|
||||
nullptr
|
||||
};
|
||||
|
||||
const HashAlgorithmDescriptor* HashAlgorithmDescriptor::find(const char* name)
|
||||
{
|
||||
unsigned count = FB_NELEM(hashAlgorithmDescriptors);
|
||||
static const HashAlgorithmDescriptor* hashAlgorithmDescriptors[] = {
|
||||
HashAlgorithmDescriptorFactory<Crc32HashContext>::getInstance("CRC32", 4),
|
||||
nullptr
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
const HashAlgorithmDescriptor* HashAlgorithmDescriptor::find(const HashAlgorithmDescriptor** hashDescriptor, const MetaName name)
|
||||
{
|
||||
for (; *hashDescriptor; hashDescriptor++)
|
||||
{
|
||||
if (strcmp(name, hashAlgorithmDescriptors[i]->name) == 0)
|
||||
return hashAlgorithmDescriptors[i];
|
||||
if (name == (*hashDescriptor)->name)
|
||||
return *hashDescriptor;
|
||||
}
|
||||
|
||||
status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << name);
|
||||
@ -171,6 +175,22 @@ const HashAlgorithmDescriptor* HashAlgorithmDescriptor::find(const char* name)
|
||||
}
|
||||
|
||||
|
||||
const HashAlgorithmDescriptor* getHashAlgorithmDesc(thread_db* tdbb, const SysFunction* function, const dsc* algDsc, bool* cHash = nullptr)
|
||||
{
|
||||
bool cryptHash = (strcmp(function->name, "CRYPT_HASH") == 0);
|
||||
if (cHash)
|
||||
*cHash = cryptHash;
|
||||
|
||||
if (!algDsc->dsc_address || !algDsc->isText())
|
||||
status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << "<not a string constant>");
|
||||
|
||||
MetaName algorithmName;
|
||||
MOV_get_metaname(tdbb, algDsc, algorithmName);
|
||||
|
||||
return HashAlgorithmDescriptor::find(cryptHash ? cryptHashAlgorithmDescriptors : hashAlgorithmDescriptors, algorithmName);
|
||||
}
|
||||
|
||||
|
||||
// constants
|
||||
const int oneDay = 86400;
|
||||
const unsigned getContextLen = 255;
|
||||
@ -200,6 +220,7 @@ void setParamsDateDiff(DataTypeUtilBase* dataTypeUtil, const SysFunction* functi
|
||||
void setParamsEncrypt(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args);
|
||||
void setParamsFirstLastDay(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||
void setParamsGetSetContext(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||
void setParamsHash(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args);
|
||||
void setParamsMakeDbkey(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||
void setParamsOverlay(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||
void setParamsPosition(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||
@ -268,7 +289,6 @@ dsc* evlBin(thread_db* tdbb, const SysFunction* function, const NestValueArray&
|
||||
dsc* evlBinShift(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||
dsc* evlCeil(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||
dsc* evlCharToUuid(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||
dsc* evlCrc32(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||
dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||
dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||
dsc* evlDecode64(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||
@ -761,6 +781,14 @@ void setParamsGetSetContext(DataTypeUtilBase*, const SysFunction*, int argsCount
|
||||
}
|
||||
|
||||
|
||||
void setParamsHash(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args)
|
||||
{
|
||||
fb_assert(argsCount == 1 || argsCount == 2);
|
||||
|
||||
setParamVarying(args[0], ttype_binary);
|
||||
}
|
||||
|
||||
|
||||
void setParamsMakeDbkey(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args)
|
||||
{
|
||||
// MAKE_DBKEY ( REL_NAME | REL_ID, RECNUM [, DPNUM [, PPNUM] ] )
|
||||
@ -1275,13 +1303,22 @@ void makeHash(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc*
|
||||
makeInt64Result(dataTypeUtil, function, result, argsCount, args);
|
||||
else if (argsCount >= 2)
|
||||
{
|
||||
if (!args[1]->dsc_address || !args[1]->isText()) // not a constant
|
||||
status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << "<not a string constant>");
|
||||
bool cryptHash;
|
||||
const HashAlgorithmDescriptor* d = getHashAlgorithmDesc(JRD_get_thread_data(), function, args[1], &cryptHash);
|
||||
|
||||
MetaName algorithmName;
|
||||
MOV_get_metaname(JRD_get_thread_data(), args[1], algorithmName);
|
||||
|
||||
result->makeVarying(HashAlgorithmDescriptor::find(algorithmName.c_str())->length, ttype_binary);
|
||||
if (cryptHash)
|
||||
result->makeVarying(d->length, ttype_binary);
|
||||
else
|
||||
{
|
||||
switch(d->length)
|
||||
{
|
||||
case 4:
|
||||
result->makeLong(0);
|
||||
break;
|
||||
default:
|
||||
fb_assert(false);
|
||||
}
|
||||
}
|
||||
result->setNullable(args[0]->isNullable());
|
||||
}
|
||||
}
|
||||
@ -3330,50 +3367,6 @@ dsc* evlEncodeHex(thread_db* tdbb, const SysFunction* function, const NestValueA
|
||||
return evlEncodeDecodeHex(tdbb, true, function, args, impure);
|
||||
}
|
||||
|
||||
|
||||
dsc* evlCrc32(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure)
|
||||
{
|
||||
crc32_state ctx;
|
||||
crc32_init(&ctx);
|
||||
|
||||
const dsc* arg = EVL_expr(tdbb, tdbb->getRequest(), args[0]);
|
||||
if (!arg) // return NULL if value is NULL
|
||||
return NULL;
|
||||
|
||||
if (arg->isBlob())
|
||||
{
|
||||
blb* blob = blb::open2(tdbb, tdbb->getRequest()->req_transaction, reinterpret_cast<const bid*>(arg->dsc_address),
|
||||
sizeof(streamBpb), streamBpb);
|
||||
|
||||
UCHAR buf[4096];
|
||||
for(;;)
|
||||
{
|
||||
const unsigned l = blob->BLB_get_data(tdbb, buf, sizeof buf, false);
|
||||
if (!l)
|
||||
break;
|
||||
crc32_update(&ctx, buf, l);
|
||||
}
|
||||
|
||||
blob->BLB_close(tdbb);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned len;
|
||||
const UCHAR* ptr = CVT_get_bytes(arg, len);
|
||||
crc32_update(&ctx, ptr, len);
|
||||
}
|
||||
|
||||
SLONG hash;
|
||||
crc32_finish(&ctx, &hash, sizeof hash);
|
||||
|
||||
dsc result;
|
||||
result.makeLong(0, &hash);
|
||||
EVL_make_value(tdbb, &result, impure);
|
||||
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
|
||||
|
||||
dsc* evlRsaEncryptDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args,
|
||||
impure_value* impure, bool encryptFlag)
|
||||
{
|
||||
@ -4558,7 +4551,7 @@ dsc* evlGetTranCN(thread_db* tdbb, const SysFunction* function, const NestValueA
|
||||
}
|
||||
|
||||
|
||||
dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
|
||||
dsc* evlHash(thread_db* tdbb, const SysFunction* function, const NestValueArray& args,
|
||||
impure_value* impure)
|
||||
{
|
||||
fb_assert(args.getCount() >= 1);
|
||||
@ -4578,12 +4571,8 @@ dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
|
||||
if (request->req_flags & req_null) // return NULL if algorithm is NULL
|
||||
return NULL;
|
||||
|
||||
if (!algorithmDesc->isText())
|
||||
status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << "<not a string constant>");
|
||||
|
||||
MetaName algorithmName;
|
||||
MOV_get_metaname(tdbb, algorithmDesc, algorithmName);
|
||||
hashContext.reset(HashAlgorithmDescriptor::find(algorithmName.c_str())->create(pool));
|
||||
const HashAlgorithmDescriptor* d = getHashAlgorithmDesc(tdbb, function, algorithmDesc);
|
||||
hashContext.reset(d->create(pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4607,29 +4596,14 @@ dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
|
||||
}
|
||||
else
|
||||
{
|
||||
UCHAR* address;
|
||||
MoveBuffer buffer;
|
||||
const ULONG length = MOV_make_string2(tdbb, value, value->getTextType(), &address, buffer, false);
|
||||
hashContext->update(address, length);
|
||||
unsigned len;
|
||||
const UCHAR* ptr = CVT_get_bytes(value, len);
|
||||
hashContext->update(ptr, len);
|
||||
}
|
||||
|
||||
HashContext::Buffer resultBuffer;
|
||||
hashContext->finish(resultBuffer);
|
||||
|
||||
if (args.getCount() >= 2)
|
||||
{
|
||||
dsc result;
|
||||
result.makeText(resultBuffer.getCount(), ttype_binary, resultBuffer.begin());
|
||||
EVL_make_value(tdbb, &result, impure);
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_assert(resultBuffer.getCount() == sizeof(SINT64));
|
||||
memcpy(&impure->vlu_misc.vlu_int64, resultBuffer.begin(), sizeof(SINT64));
|
||||
|
||||
// make descriptor for return value
|
||||
impure->vlu_desc.makeInt64(0, &impure->vlu_misc.vlu_int64);
|
||||
}
|
||||
dsc result;
|
||||
hashContext->finish(result);
|
||||
EVL_make_value(tdbb, &result, impure);
|
||||
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
@ -6369,7 +6343,6 @@ const SysFunction SysFunction::functions[] =
|
||||
{"ATAN2", 2, 2, setParamsDouble, makeDoubleResult, evlAtan2, NULL},
|
||||
{"BASE64_DECODE", 1, 1, NULL, makeDecode64, evlDecode64, NULL},
|
||||
{"BASE64_ENCODE", 1, 1, NULL, makeEncode64, evlEncode64, NULL},
|
||||
{"CRC32", 1, 1, NULL, makeLongResult, evlCrc32, NULL},
|
||||
{"BIN_AND", 2, -1, setParamsBin, makeBin, evlBin, (void*) funBinAnd},
|
||||
{"BIN_NOT", 1, 1, setParamsBin, makeBin, evlBin, (void*) funBinNot},
|
||||
{"BIN_OR", 2, -1, setParamsBin, makeBin, evlBin, (void*) funBinOr},
|
||||
@ -6385,6 +6358,7 @@ const SysFunction SysFunction::functions[] =
|
||||
{"COS", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCos},
|
||||
{"COSH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCosh},
|
||||
{"COT", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCot},
|
||||
{"CRYPT_HASH", 2, 2, setParamsHash, makeHash, evlHash, NULL},
|
||||
{"DATEADD", 3, 3, setParamsDateAdd, makeDateAdd, evlDateAdd, NULL},
|
||||
{"DATEDIFF", 3, 3, setParamsDateDiff, makeInt64Result, evlDateDiff, NULL},
|
||||
{"DECRYPT", 7, 7, setParamsEncrypt, makeDecrypt, evlDecrypt, NULL},
|
||||
@ -6393,7 +6367,7 @@ const SysFunction SysFunction::functions[] =
|
||||
{"FIRST_DAY", 2, 2, setParamsFirstLastDay, makeFirstLastDayResult, evlFirstLastDay, (void*) funFirstDay},
|
||||
{"FLOOR", 1, 1, setParamsDblDec, makeCeilFloor, evlFloor, NULL},
|
||||
{"GEN_UUID", 0, 0, NULL, makeUuid, evlGenUuid, NULL},
|
||||
{"HASH", 1, 2, NULL, makeHash, evlHash, NULL},
|
||||
{"HASH", 1, 2, setParamsHash, makeHash, evlHash, NULL},
|
||||
{"HEX_DECODE", 1, 1, NULL, makeDecodeHex, evlDecodeHex, NULL},
|
||||
{"HEX_ENCODE", 1, 1, NULL, makeEncodeHex, evlEncodeHex, NULL},
|
||||
{"LAST_DAY", 2, 2, setParamsFirstLastDay, makeFirstLastDayResult, evlFirstLastDay, (void*) funLastDay},
|
||||
|
Loading…
Reference in New Issue
Block a user