forked from wolfSSL/wolfssl
Merge pull request #3885 from JacobBarthelmeh/StaticAnalysisTests
Static analysis fixes for items listed as high priority
This commit is contained in:
57
src/ssl.c
57
src/ssl.c
@ -9827,8 +9827,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c,
|
|||||||
gn = wolfSSL_GENERAL_NAME_new();
|
gn = wolfSSL_GENERAL_NAME_new();
|
||||||
if (gn == NULL) {
|
if (gn == NULL) {
|
||||||
WOLFSSL_MSG("Error creating GENERAL_NAME");
|
WOLFSSL_MSG("Error creating GENERAL_NAME");
|
||||||
wolfSSL_sk_free(sk);
|
goto err;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gn->type = dns->type;
|
gn->type = dns->type;
|
||||||
@ -9836,18 +9835,14 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c,
|
|||||||
if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name,
|
if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name,
|
||||||
gn->d.ia5->length) != WOLFSSL_SUCCESS) {
|
gn->d.ia5->length) != WOLFSSL_SUCCESS) {
|
||||||
WOLFSSL_MSG("ASN1_STRING_set failed");
|
WOLFSSL_MSG("ASN1_STRING_set failed");
|
||||||
wolfSSL_GENERAL_NAME_free(gn);
|
goto err;
|
||||||
wolfSSL_sk_free(sk);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dns = dns->next;
|
dns = dns->next;
|
||||||
if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) !=
|
if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) !=
|
||||||
WOLFSSL_SUCCESS) {
|
WOLFSSL_SUCCESS) {
|
||||||
WOLFSSL_MSG("Error pushing ASN1 object onto stack");
|
WOLFSSL_MSG("Error pushing ASN1 object onto stack");
|
||||||
wolfSSL_GENERAL_NAME_free(gn);
|
goto err;
|
||||||
wolfSSL_sk_free(sk);
|
|
||||||
sk = NULL;
|
|
||||||
}
|
}
|
||||||
/* null so that it doesn't get pushed again after switch */
|
/* null so that it doesn't get pushed again after switch */
|
||||||
gn = NULL;
|
gn = NULL;
|
||||||
@ -16510,7 +16505,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
wc_RemoveErrorNode(0);
|
wc_RemoveErrorNode(0);
|
||||||
}
|
}
|
||||||
} while (ret >= 0);
|
} while (ret >= 0);
|
||||||
wolfSSL_BIO_write(bio, "", 1);
|
if (wolfSSL_BIO_write(bio, "", 1) != 1) {
|
||||||
|
WOLFSSL_MSG("Issue writing final string terminator");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* !NO_BIO */
|
#endif /* !NO_BIO */
|
||||||
#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */
|
#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */
|
||||||
@ -32405,6 +32402,10 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_BN_to_ASN1_INTEGER(const WOLFSSL_BIGNUM *bn, WOLFS
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
len = wolfSSL_BN_bn2bin(bn, a->data);
|
len = wolfSSL_BN_bn2bin(bn, a->data);
|
||||||
|
if (len < 0) {
|
||||||
|
wolfSSL_ASN1_INTEGER_free(a);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
a->length = len;
|
a->length = len;
|
||||||
|
|
||||||
@ -42154,6 +42155,7 @@ cleanup:
|
|||||||
pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM);
|
pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM);
|
||||||
if (pem == NULL)
|
if (pem == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
XMEMSET(pem, 0, l);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (wc_PemGetHeaderFooter(type, NULL, &footer) != 0) {
|
if (wc_PemGetHeaderFooter(type, NULL, &footer) != 0) {
|
||||||
@ -48818,7 +48820,7 @@ int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1,
|
|||||||
XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
|
XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||||
asn1->isDynamic = 0;
|
asn1->isDynamic = 0;
|
||||||
}
|
}
|
||||||
XMEMSET(asn1->intData, 0, sizeof(WOLFSSL_ASN1_INTEGER));
|
XMEMSET(asn1->intData, 0, WOLFSSL_ASN1_INTEGER_MAX);
|
||||||
asn1->data = asn1->intData;
|
asn1->data = asn1->intData;
|
||||||
asn1->length = 0;
|
asn1->length = 0;
|
||||||
asn1->negative = 0;
|
asn1->negative = 0;
|
||||||
@ -48847,7 +48849,7 @@ int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1,
|
|||||||
len = asn1->length + (lineLen/2);
|
len = asn1->length + (lineLen/2);
|
||||||
/* Check if it will fit in static memory and
|
/* Check if it will fit in static memory and
|
||||||
* save space for the ASN tag in front */
|
* save space for the ASN tag in front */
|
||||||
if (len > (int)(sizeof(asn1->intData) - extraTagSz)) {
|
if (len > (int)(WOLFSSL_ASN1_INTEGER_MAX - extraTagSz)) {
|
||||||
/* Allocate mem for data */
|
/* Allocate mem for data */
|
||||||
if (asn1->isDynamic) {
|
if (asn1->isDynamic) {
|
||||||
byte* tmp = (byte*)XREALLOC(asn1->data, len + extraTagSz, NULL,
|
byte* tmp = (byte*)XREALLOC(asn1->data, len + extraTagSz, NULL,
|
||||||
@ -48859,12 +48861,17 @@ int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1,
|
|||||||
asn1->data = tmp;
|
asn1->data = tmp;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/* Up to this point asn1->data pointed to asn1->intData.
|
||||||
|
* Now that the size has grown larger than intData can handle
|
||||||
|
* the asn1 structure moves to a dynamic type with isDynamic
|
||||||
|
* flag being set and asn1->data being malloc'd. */
|
||||||
asn1->data = (byte*)XMALLOC(len + extraTagSz, NULL,
|
asn1->data = (byte*)XMALLOC(len + extraTagSz, NULL,
|
||||||
DYNAMIC_TYPE_OPENSSL);
|
DYNAMIC_TYPE_OPENSSL);
|
||||||
if (!asn1->data) {
|
if (!asn1->data) {
|
||||||
WOLFSSL_MSG("malloc error");
|
WOLFSSL_MSG("malloc error");
|
||||||
return WOLFSSL_FAILURE;
|
return WOLFSSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
asn1->isDynamic = 1;
|
||||||
XMEMCPY(asn1->data, asn1->intData, asn1->length);
|
XMEMCPY(asn1->data, asn1->intData, asn1->length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51415,7 +51422,7 @@ int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n)
|
|||||||
int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
|
int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int len = bits / 8;
|
int len;
|
||||||
int initTmpRng = 0;
|
int initTmpRng = 0;
|
||||||
WC_RNG* rng = NULL;
|
WC_RNG* rng = NULL;
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
@ -51430,9 +51437,19 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
|
|||||||
(void)bottom;
|
(void)bottom;
|
||||||
WOLFSSL_MSG("wolfSSL_BN_rand");
|
WOLFSSL_MSG("wolfSSL_BN_rand");
|
||||||
|
|
||||||
|
if (bits <= 0) {
|
||||||
|
return WOLFSSL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = bits / 8;
|
||||||
if (bits % 8)
|
if (bits % 8)
|
||||||
len++;
|
len++;
|
||||||
|
|
||||||
|
/* has to be a length of at least 1 since we set buf[0] and buf[len-1] */
|
||||||
|
if (len < 1) {
|
||||||
|
return WOLFSSL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
|
tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
|
||||||
@ -51488,7 +51505,7 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
|
|||||||
int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
|
int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int len = bits / 8;
|
int len;
|
||||||
int initTmpRng = 0;
|
int initTmpRng = 0;
|
||||||
WC_RNG* rng = NULL;
|
WC_RNG* rng = NULL;
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
@ -51499,11 +51516,23 @@ int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
|
|||||||
byte buff[1024];
|
byte buff[1024];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WOLFSSL_MSG("wolfSSL_BN_rand");
|
WOLFSSL_ENTER("wolfSSL_BN_pseudo_rand");
|
||||||
|
|
||||||
|
if (bits <= 0) {
|
||||||
|
return WOLFSSL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = bits / 8;
|
||||||
if (bits % 8)
|
if (bits % 8)
|
||||||
len++;
|
len++;
|
||||||
|
|
||||||
|
/* has to be a length of at least 1 since we set buf[0] and buf[len-1] */
|
||||||
|
if (top == 1 || top == 0 || bottom == 1) {
|
||||||
|
if (len < 1) {
|
||||||
|
return WOLFSSL_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
70
tests/api.c
70
tests/api.c
@ -29916,6 +29916,51 @@ static void test_wolfSSL_ASN1_BIT_STRING(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_wolfSSL_a2i_ASN1_INTEGER(void)
|
||||||
|
{
|
||||||
|
#ifdef OPENSSL_EXTRA
|
||||||
|
BIO *bio, *out;
|
||||||
|
ASN1_INTEGER* ai;
|
||||||
|
char buf[] = "123456\n12345\n112345678912345678901234567890\n";
|
||||||
|
char tmp[1024];
|
||||||
|
int tmpSz;
|
||||||
|
|
||||||
|
const char expected1[] = "123456";
|
||||||
|
const char expected2[] = "112345678912345678901234567890";
|
||||||
|
|
||||||
|
printf(testingFmt, "test_wolfSSL_a2i_ASN1_INTEGER()");
|
||||||
|
|
||||||
|
AssertNotNull(bio = BIO_new_mem_buf(buf, -1));
|
||||||
|
AssertNotNull(out = BIO_new(BIO_s_mem()));
|
||||||
|
AssertNotNull(ai = ASN1_INTEGER_new());
|
||||||
|
|
||||||
|
/* read first line */
|
||||||
|
AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS);
|
||||||
|
AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 6);
|
||||||
|
XMEMSET(tmp, 0, 1024);
|
||||||
|
tmpSz = BIO_read(out, tmp, 1024);
|
||||||
|
AssertIntEQ(tmpSz, 6);
|
||||||
|
AssertIntEQ(XMEMCMP(tmp, expected1, tmpSz), 0);
|
||||||
|
|
||||||
|
/* fail on second line (not % 2) */
|
||||||
|
AssertIntNE(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS);
|
||||||
|
|
||||||
|
/* read 3rd long line */
|
||||||
|
AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS);
|
||||||
|
AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 30);
|
||||||
|
XMEMSET(tmp, 0, 1024);
|
||||||
|
tmpSz = BIO_read(out, tmp, 1024);
|
||||||
|
AssertIntEQ(tmpSz, 30);
|
||||||
|
AssertIntEQ(XMEMCMP(tmp, expected2, tmpSz), 0);
|
||||||
|
|
||||||
|
BIO_free(out);
|
||||||
|
BIO_free(bio);
|
||||||
|
ASN1_INTEGER_free(ai);
|
||||||
|
|
||||||
|
printf(resultFmt, passed);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void test_wolfSSL_DES_ecb_encrypt(void)
|
static void test_wolfSSL_DES_ecb_encrypt(void)
|
||||||
{
|
{
|
||||||
@ -30998,6 +31043,29 @@ static void test_wolfSSL_RAND_bytes(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_wolfSSL_BN_rand(void)
|
||||||
|
{
|
||||||
|
#if defined(OPENSSL_EXTRA)
|
||||||
|
BIGNUM* bn;
|
||||||
|
|
||||||
|
printf(testingFmt, "wolfSSL_BN_rand()");
|
||||||
|
|
||||||
|
AssertNotNull(bn = BN_new());
|
||||||
|
AssertIntNE(BN_rand(bn, 0, 0, 0), SSL_SUCCESS);
|
||||||
|
BN_free(bn);
|
||||||
|
|
||||||
|
AssertNotNull(bn = BN_new());
|
||||||
|
AssertIntEQ(BN_rand(bn, 8, 0, 0), SSL_SUCCESS);
|
||||||
|
BN_free(bn);
|
||||||
|
|
||||||
|
AssertNotNull(bn = BN_new());
|
||||||
|
AssertIntEQ(BN_rand(bn, 64, 0, 0), SSL_SUCCESS);
|
||||||
|
BN_free(bn);
|
||||||
|
|
||||||
|
printf(resultFmt, passed);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void test_wolfSSL_pseudo_rand(void)
|
static void test_wolfSSL_pseudo_rand(void)
|
||||||
{
|
{
|
||||||
#if defined(OPENSSL_EXTRA)
|
#if defined(OPENSSL_EXTRA)
|
||||||
@ -42220,6 +42288,7 @@ void ApiTest(void)
|
|||||||
#endif
|
#endif
|
||||||
test_wolfSSL_ASN1_STRING();
|
test_wolfSSL_ASN1_STRING();
|
||||||
test_wolfSSL_ASN1_BIT_STRING();
|
test_wolfSSL_ASN1_BIT_STRING();
|
||||||
|
test_wolfSSL_a2i_ASN1_INTEGER();
|
||||||
test_wolfSSL_X509();
|
test_wolfSSL_X509();
|
||||||
test_wolfSSL_X509_VERIFY_PARAM();
|
test_wolfSSL_X509_VERIFY_PARAM();
|
||||||
test_wolfSSL_X509_sign();
|
test_wolfSSL_X509_sign();
|
||||||
@ -42242,6 +42311,7 @@ void ApiTest(void)
|
|||||||
test_wolfSSL_THREADID_hash();
|
test_wolfSSL_THREADID_hash();
|
||||||
test_wolfSSL_RAND_set_rand_method();
|
test_wolfSSL_RAND_set_rand_method();
|
||||||
test_wolfSSL_RAND_bytes();
|
test_wolfSSL_RAND_bytes();
|
||||||
|
test_wolfSSL_BN_rand();
|
||||||
test_wolfSSL_pseudo_rand();
|
test_wolfSSL_pseudo_rand();
|
||||||
test_wolfSSL_PKCS8_Compat();
|
test_wolfSSL_PKCS8_Compat();
|
||||||
test_wolfSSL_PKCS8_d2i();
|
test_wolfSSL_PKCS8_d2i();
|
||||||
|
@ -2126,7 +2126,6 @@ int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz,
|
|||||||
const byte* pub, word32 pubSz)
|
const byte* pub, word32 pubSz)
|
||||||
{
|
{
|
||||||
byte havePriv, havePub;
|
byte havePriv, havePub;
|
||||||
mp_int *keyPriv = NULL, *keyPub = NULL;
|
|
||||||
|
|
||||||
if (key == NULL) {
|
if (key == NULL) {
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
@ -2154,7 +2153,6 @@ int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz,
|
|||||||
mp_clear(&key->priv);
|
mp_clear(&key->priv);
|
||||||
havePriv = 0;
|
havePriv = 0;
|
||||||
} else {
|
} else {
|
||||||
keyPriv = &key->priv;
|
|
||||||
WOLFSSL_MSG("DH Private Key Set");
|
WOLFSSL_MSG("DH Private Key Set");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2172,16 +2170,14 @@ int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz,
|
|||||||
if (mp_read_unsigned_bin(&key->pub, pub, pubSz) != MP_OKAY) {
|
if (mp_read_unsigned_bin(&key->pub, pub, pubSz) != MP_OKAY) {
|
||||||
mp_clear(&key->pub);
|
mp_clear(&key->pub);
|
||||||
havePub = 0;
|
havePub = 0;
|
||||||
|
if (havePriv) {
|
||||||
|
mp_clear(&key->priv);
|
||||||
|
havePriv = 0; /* set to 0 to error out with failed read pub */
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
keyPub = &key->pub;
|
|
||||||
WOLFSSL_MSG("DH Public Key Set");
|
WOLFSSL_MSG("DH Public Key Set");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Free Memory if error occurred */
|
|
||||||
if (havePriv == 0 && keyPriv != NULL)
|
|
||||||
mp_clear(keyPriv);
|
|
||||||
if (havePub == 0 && keyPub != NULL)
|
|
||||||
mp_clear(keyPub);
|
|
||||||
|
|
||||||
if (havePriv == 0 && havePub == 0) {
|
if (havePriv == 0 && havePub == 0) {
|
||||||
return MEMORY_E;
|
return MEMORY_E;
|
||||||
|
@ -6868,17 +6868,24 @@ WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap)
|
|||||||
XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY));
|
XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY));
|
||||||
pkey->heap = heap;
|
pkey->heap = heap;
|
||||||
pkey->type = WOLFSSL_EVP_PKEY_DEFAULT;
|
pkey->type = WOLFSSL_EVP_PKEY_DEFAULT;
|
||||||
|
|
||||||
|
/* init of mutex needs to come before wolfSSL_EVP_PKEY_free */
|
||||||
|
ret = wc_InitMutex(&pkey->refMutex);
|
||||||
|
if (ret != 0){
|
||||||
|
XFREE(pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
|
||||||
|
WOLFSSL_MSG("Issue initializing mutex");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef HAVE_FIPS
|
#ifndef HAVE_FIPS
|
||||||
ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID);
|
ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID);
|
||||||
#else
|
#else
|
||||||
ret = wc_InitRng(&pkey->rng);
|
ret = wc_InitRng(&pkey->rng);
|
||||||
#endif
|
#endif
|
||||||
pkey->references = 1;
|
pkey->references = 1;
|
||||||
wc_InitMutex(&pkey->refMutex); /* init of mutex needs to come before
|
|
||||||
* wolfSSL_EVP_PKEY_free */
|
|
||||||
if (ret != 0){
|
if (ret != 0){
|
||||||
wolfSSL_EVP_PKEY_free(pkey);
|
wolfSSL_EVP_PKEY_free(pkey);
|
||||||
WOLFSSL_MSG("memory failure");
|
WOLFSSL_MSG("Issue initializing RNG");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user