Okay, I’ve written my first functional PHP extension. It worked but it was a proof-of-concept only. Now I’m writing another one which actually does what the boss wants.
What I’d like to know, from all you PHP-heads out there, is whether this code makes sense. Have I got a good grasp of things like emalloc and the like, or is there stuff there that’s going to turn around later and try to bite my hand off?
Below is the code for one of the functions. It returns a base64 of a string that has also been Blowfish encrypted. When the function is called, it is supplied with two strings, the text to encrypt and encode, and the key for the encryption phase. It’s not using PHP’s own base64 functions because, at this point, I don’t know how to link to them. And it’s not using PHP’s own mcrypt functions for the same reason. Instead, it links in the SSLeay BF_ecb_encrypt functions.
PHP_FUNCTION(Blowfish_Base64_encode)
{
char *psData = NULL;
char *psKey = NULL;
int argc = ZEND_NUM_ARGS();
int psData_len;
int psKey_len;
char *Buffer = NULL;
char *pBuffer = NULL;
char *Encoded = NULL;
BF_KEY Context;
int i = 0;
unsigned char Block[ 8 ];
unsigned char * pBlock = Block;
char *plaintext;
int plaintext_len;
int cipher_len = 0;
if (zend_parse_parameters(argc TSRMLS_CC, "ss", &psData, &psData_len, &psKey, &psKey_len) == FAILURE)
return;
Buffer = (char *) emalloc( psData_len * 2 );
pBuffer = Buffer;
Encoded = (char *) emalloc( psData_len * 4 );
BF_set_key( &Context, psKey_len, psKey );
plaintext = psData;
plaintext_len = psData_len;
for (;;)
{
if (plaintext_len--)
{
Block[ i++ ] = *plaintext++;
if (i == 8 )
{
BF_ecb_encrypt( Block, pBuffer, &Context, BF_ENCRYPT );
pBuffer += 8;
cipher_len += 8;
memset( Block, 0, 8 );
i = 0;
}
} else {
BF_ecb_encrypt( Block, pBuffer, &Context, BF_ENCRYPT );
cipher_len += 8;
break;
}
}
b64_encode( Encoded, Buffer, cipher_len );
RETURN_STRINGL( Encoded, strlen( Encoded ), 0 );
}
You’ll notice that I have two emalloc calls, for Encoded and for Buffer. Only Encoded is passed back to the caller, so I’m concerned that Buffer won’t be freed. Is that the case? Should I use malloc/free for Buffer?
If there are any other glaring errors, I’d really appreciate knowing.
Yes, you should free it with
efreebefore returning.Although PHP has safety net and memory allocated with
emallocwill be freed at the end of the request, it’s still a bug to leak memory and, depending you will warned if running a debug build withreport_memleaks = On.