You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Garrett Rooney <ro...@electricjellyfish.net> on 2005/08/14 22:21:48 UTC
smtpd_request_rec questions
I was just looking at the smtpd_request_rec in mod_smtpd, and I had a
few questions.
It seems that extensions and rcpt info is being stored in an apr_hash_t,
but it's only being keyed by integer. If you're only going to use ints
as keys, it seems like an apr_array_header_t would be more appropriate.
Also, while the extensions has is specifically allocating its keys,
the rcpt_to hash is reusing the r_index variable each time, so if more
than one entry is added things aren't going to work, since that location
in memory is having its value changed after its been used as a key.
Anyway, I'd be happy to produce patches to either switch to an array or
fix the key issue in the rcpt_to section, depending on which way we want
to go. Personally, I'd prefer the array version though.
-garrett
Re: [PATCH] use arrays in smtpd_request_rec (was Re: smtpd_request_rec questions)
Posted by Rian Hunter <ri...@MIT.EDU>.
On Aug 14, 2005, at 11:08 PM, Garrett Rooney wrote:
> Rian Hunter wrote:
>
>> This patch looks good but I have some questions. You seem to use
>> the returned pointers from apr_array_push without checking if
>> they are NULL. Even in apr_array_push, apr_palloc is used without
>> checking for NULL even though apr_palloc can definitely return NULL.
>> Because of that, I'm not sure whether or not you don't check for
>> NULL on purpose. Could you explain? Thanks.
>>
>
> Well, it depends on what your general attitude towards checking for
> errors in memory allocation. In many projects it's generally
> considered to be the kind of error you can't effectively recover
> from anyway, so cluttering up the code with if (foo == NULL) checks
> is kind of pointless, you're likely to have been killed by a kernel
> OOM checker before that can do anything useful, or you could be on
> an OS that doesn't even return NULL (memory overcommit), so the
> checks are pointless anyway. The only way to be safe is to make
> sure that algorithmicly your program can't allocate unbounded
> amounts of memory, then tune your box and app so that this kind of
> problem doesn't happen in practice.
>
> APR generally doesn't bother checking for this kind of error for
> just this reason, same with Subversion and if I'm not mistaken
> Apache HTTPD itself.
>
> -garrett
>
Thanks for this information! After looking at code in httpd it seems
this is the case. I'll change the mod_smtpd code to reflect this
convention.
-rian
Re: [PATCH] use arrays in smtpd_request_rec (was Re: smtpd_request_rec
questions)
Posted by Garrett Rooney <ro...@electricjellyfish.net>.
Rian Hunter wrote:
> This patch looks good but I have some questions. You seem to use the
> returned pointers from apr_array_push without checking if they are
> NULL. Even in apr_array_push, apr_palloc is used without checking for
> NULL even though apr_palloc can definitely return NULL.
>
> Because of that, I'm not sure whether or not you don't check for NULL
> on purpose. Could you explain? Thanks.
Well, it depends on what your general attitude towards checking for
errors in memory allocation. In many projects it's generally considered
to be the kind of error you can't effectively recover from anyway, so
cluttering up the code with if (foo == NULL) checks is kind of
pointless, you're likely to have been killed by a kernel OOM checker
before that can do anything useful, or you could be on an OS that
doesn't even return NULL (memory overcommit), so the checks are
pointless anyway. The only way to be safe is to make sure that
algorithmicly your program can't allocate unbounded amounts of memory,
then tune your box and app so that this kind of problem doesn't happen
in practice.
APR generally doesn't bother checking for this kind of error for just
this reason, same with Subversion and if I'm not mistaken Apache HTTPD
itself.
-garrett
Re: [PATCH] use arrays in smtpd_request_rec (was Re: smtpd_request_rec questions)
Posted by Rian Hunter <ri...@MIT.EDU>.
This patch looks good but I have some questions. You seem to use the
returned pointers from apr_array_push without checking if they are
NULL. Even in apr_array_push, apr_palloc is used without checking for
NULL even though apr_palloc can definitely return NULL.
Because of that, I'm not sure whether or not you don't check for NULL
on purpose. Could you explain? Thanks.
-rian
On Aug 14, 2005, at 8:52 PM, Garrett Rooney wrote:
> Garrett Rooney wrote:
>
>> Rian Hunter wrote:
>>
>>> Ah I didn't even realize the key allocation, I'll fix that. Thanks!
>>>
>>> The reason I don't use an apr_array_t or similar is that I
>>> thought that the number of elements in that type has to be fixed
>>> and can't be automatically extended and allocated on the fly, If
>>> I'm wrong I can change these structures to use apr_array_t (or
>>> you can send in a patch if you like).
>>>
>> APR arrays are variable length, you use apr_array_push and
>> apr_array_pop to add and remove entries. I'll throw together the
>> patch sometime today.
>>
>
> And here's the patch. This is totally untested, since I haven't
> yet gotten around to making mod_smtpd do anything other than
> compile yet, but it's pretty simple and should give you an idea of
> what I meant.
>
> -garrett
>
> * mod_smtpd.h
> (smtpd_request_rec::e_index,
> smtpd_request_rec::r_index): removed.
> (smtpd_request_rec::extensions,
> smtpd_request_rec::rcpt_to): change from a hash to an array.
>
> * smtp_core.c
> (smtpd_register_extension): push the extension onto the array.
> (smtpd_clear_request_rec): allocate the new arrays.
>
> * smtp_protocol.c
> (helo): remove ext and ext_next variables, iterate over the array
> instead of doing backflips to iterate over the hash.
> (rcpt): remove new_elt variable, just push the rcpt address onto
> the array.
> Index: mod_smtpd.h
> ===================================================================
> --- mod_smtpd.h (revision 232680)
> +++ mod_smtpd.h (working copy)
> @@ -90,16 +90,13 @@
> // by default smtp
> smtpd_protocol_type extended;
>
> - // current max index of the extension hash
> - int e_index;
> - apr_hash_t *extensions;
> + apr_array_header_t *extensions;
>
> // string of who this mail is from
> char *mail_from;
> - // current max index of the rcpt_to hash
> - int r_index;
> - apr_hash_t *rcpt_to;
>
> + apr_array_header_t *rcpt_to;
> +
> // hostname we were helo'd with
> char *helo;
> } smtpd_request_rec;
> Index: smtp_protocol.c
> ===================================================================
> --- smtp_protocol.c (revision 232680)
> +++ smtp_protocol.c (working copy)
> @@ -121,7 +121,6 @@
>
> HANDLER_DECLARE(ehlo) {
> int i = 0, retval = 0;
> - char *ext = NULL, *ext_next;
> smtpd_request_rec *sr = smtpd_get_request_rec(r);
>
> if (buffer[0] == '\0') {
> @@ -161,21 +160,13 @@
> }
>
> // print out extension
> - ext = apr_hash_get(sr->extensions, &i, sizeof(i));
> retval = 250;
>
> - if (ext) {
> + if (sr->extensions->nelts) {
> ap_rprintf(r, "%d-%s\r\n", 250, sr->helo);
> -
> - while (1) {
> - i++;
> - if ((ext_next = apr_hash_get(sr->extensions, &i, sizeof(i)))) {
> - ap_rprintf(r, "%d-%s\r\n", 250, ext);
> - } else {
> - ap_rprintf(r, "%d %s\r\n", 250, ext);
> - break;
> - }
> - ext = ext_next;
> +
> + for (i = 0; i < sr->extensions->nelts; ++i) {
> + ap_rprintf(r, "%d-%s\r\n", 250, ((char **)sr->extensions-
> >nelts)[i]);
> }
> } else {
> ap_rprintf(r, "%d %s\r\n", 250, sr->helo);
> @@ -344,7 +335,6 @@
> char *loc;
> char *allocated_string;
> int retval = 0;
> - int *new_elt;
>
> // need mail first
> if ((sr->state_vector != SMTPD_STATE_GOT_MAIL) &&
> @@ -413,19 +403,8 @@
> // add a recipient
>
> if ((allocated_string = apr_pstrdup(sr->p, loc))) {
> - new_elt = apr_palloc(sr->p, sizeof(int));
> + (*((char **)apr_array_push(sr->rcpt_to))) = allocated_string;
>
> - if (!new_elt) {
> - ap_rprintf(r, "%d %s\r\n", 421, "Error: Internal");
> - // out of memory close connection
> - retval = 0;
> - goto end;
> - }
> -
> - *new_elt = sr->r_index;
> - apr_hash_set(sr->rcpt_to, new_elt,
> - sizeof(*new_elt), allocated_string);
> - sr->r_index++;
> sr->state_vector = SMTPD_STATE_GOT_RCPT;
>
> ap_rprintf(r, "%d %s\r\n", 250, "Ok");
> Index: smtp_core.c
> ===================================================================
> --- smtp_core.c (revision 232680)
> +++ smtp_core.c (working copy)
> @@ -127,11 +127,7 @@
> SMTPD_DECLARE_NONSTD(void)
> smtpd_register_extension(smtpd_request_rec *sr, const char *line)
> {
> - int *cur = apr_palloc(sr->p, sizeof(int));
> - *cur = sr->e_index;
> -
> - apr_hash_set(sr->extensions, cur, sizeof(*cur), line);
> - (sr->e_index)++;
> + (*((char **)apr_array_push(sr->extensions))) = apr_pstrdup(sr-
> >p, line);
> }
>
> // how to reset the transaction
> @@ -154,10 +150,8 @@
> sr->state_vector = SMTPD_STATE_GOT_NOTHING;
> sr->tfp = NULL;
> sr->extended = SMTPD_PROTOCOL_SMTP;
> - sr->e_index = 0;
> - sr->extensions = apr_hash_make(sr->p);
> - sr->r_index = 0;
> - sr->rcpt_to = apr_hash_make(sr->p);
> + sr->extensions = apr_array_make(sr->p, 5, sizeof(char *));
> + sr->rcpt_to = apr_array_make(sr->p, 5, sizeof(char *));
> sr->mail_from = NULL;
> sr->helo = NULL;
> }
>
Re: [PATCH] use arrays in smtpd_request_rec
Posted by Rian Hunter <ri...@MIT.EDU>.
On Aug 15, 2005, at 10:05 PM, Garrett Rooney wrote:
> Joe Schaefer wrote:
>
>> Garrett Rooney <ro...@electricjellyfish.net> writes:
>>
>>> Index: smtp_protocol.c
>>> ===================================================================
>>> --- smtp_protocol.c (revision 232680)
>>> +++ smtp_protocol.c (working copy)
>>>
>> [...]
>>
>>> + for (i = 0; i < sr->extensions->nelts; ++i) {
>>> + ap_rprintf(r, "%d-%s\r\n", 250, ((char **)sr->extensions-
>>> >nelts)[i]);
>>>
>>
>> ^^^^^
>> That should be "elts", shouldn't it?
>>
>
> Yes indeed, it should. One of the problems with data structures
> that require casting in order to access what you've stored in
> them... The version that Rian committed is slightly different, but
> still has the same problem. I'd post a patch, but it's probably
> faster to fix it by hand than it is to detach a patch from an email
> and apply it.
>
> Over in Subversion-land we have a couple of macros defined for
> dealing with apr arrays, they make it rather difficult to make this
> kind of mistake, and I'd love to see them in the main APR release,
> but the last time it was brought up I believe someone objected to
> their inclusion...
>
> -garrett
>
Fixed. I didn't even catch this because I don't test mod_smtpd with a
plugin that registers extensions. Things like this beckon some kind
of test suite module. Someone can get to this after mod_smtpd is redone.
-rian
Re: [PATCH] use arrays in smtpd_request_rec
Posted by Paul Querna <ch...@force-elite.com>.
Garrett Rooney wrote:
[...]
>>> + for (i = 0; i < sr->extensions->nelts; ++i) {
>>> + ap_rprintf(r, "%d-%s\r\n", 250, ((char
>>> **)sr->extensions->nelts)[i]);
>>
>>
>> ^^^^^
>>
>> That should be "elts", shouldn't it?
>>
>
> Yes indeed, it should. One of the problems with data structures that
> require casting in order to access what you've stored in them... The
> version that Rian committed is slightly different, but still has the
> same problem. I'd post a patch, but it's probably faster to fix it by
> hand than it is to detach a patch from an email and apply it.
>
> Over in Subversion-land we have a couple of macros defined for dealing
> with apr arrays, they make it rather difficult to make this kind of
> mistake, and I'd love to see them in the main APR release, but the last
> time it was brought up I believe someone objected to their inclusion...
I don't object, it sounds like a bloody good idea to me.
-Paul
Re: [PATCH] use arrays in smtpd_request_rec
Posted by Garrett Rooney <ro...@electricjellyfish.net>.
Joe Schaefer wrote:
> Garrett Rooney <ro...@electricjellyfish.net> writes:
>
>
>>Index: smtp_protocol.c
>>===================================================================
>>--- smtp_protocol.c (revision 232680)
>>+++ smtp_protocol.c (working copy)
>
>
> [...]
>
>>+ for (i = 0; i < sr->extensions->nelts; ++i) {
>>+ ap_rprintf(r, "%d-%s\r\n", 250, ((char **)sr->extensions->nelts)[i]);
>
> ^^^^^
>
> That should be "elts", shouldn't it?
>
Yes indeed, it should. One of the problems with data structures that
require casting in order to access what you've stored in them... The
version that Rian committed is slightly different, but still has the
same problem. I'd post a patch, but it's probably faster to fix it by
hand than it is to detach a patch from an email and apply it.
Over in Subversion-land we have a couple of macros defined for dealing
with apr arrays, they make it rather difficult to make this kind of
mistake, and I'd love to see them in the main APR release, but the last
time it was brought up I believe someone objected to their inclusion...
-garrett
Re: [PATCH] use arrays in smtpd_request_rec
Posted by Joe Schaefer <jo...@sunstarsys.com>.
Garrett Rooney <ro...@electricjellyfish.net> writes:
> Index: smtp_protocol.c
> ===================================================================
> --- smtp_protocol.c (revision 232680)
> +++ smtp_protocol.c (working copy)
[...]
> + for (i = 0; i < sr->extensions->nelts; ++i) {
> + ap_rprintf(r, "%d-%s\r\n", 250, ((char **)sr->extensions->nelts)[i]);
^^^^^
That should be "elts", shouldn't it?
--
Joe Schaefer
[PATCH] use arrays in smtpd_request_rec (was Re: smtpd_request_rec
questions)
Posted by Garrett Rooney <ro...@electricjellyfish.net>.
Garrett Rooney wrote:
> Rian Hunter wrote:
>
>> Ah I didn't even realize the key allocation, I'll fix that. Thanks!
>>
>> The reason I don't use an apr_array_t or similar is that I thought
>> that the number of elements in that type has to be fixed and can't be
>> automatically extended and allocated on the fly, If I'm wrong I can
>> change these structures to use apr_array_t (or you can send in a
>> patch if you like).
>
>
> APR arrays are variable length, you use apr_array_push and apr_array_pop
> to add and remove entries. I'll throw together the patch sometime today.
And here's the patch. This is totally untested, since I haven't yet
gotten around to making mod_smtpd do anything other than compile yet,
but it's pretty simple and should give you an idea of what I meant.
-garrett
* mod_smtpd.h
(smtpd_request_rec::e_index,
smtpd_request_rec::r_index): removed.
(smtpd_request_rec::extensions,
smtpd_request_rec::rcpt_to): change from a hash to an array.
* smtp_core.c
(smtpd_register_extension): push the extension onto the array.
(smtpd_clear_request_rec): allocate the new arrays.
* smtp_protocol.c
(helo): remove ext and ext_next variables, iterate over the array
instead of doing backflips to iterate over the hash.
(rcpt): remove new_elt variable, just push the rcpt address onto
the array.
Re: smtpd_request_rec questions
Posted by Garrett Rooney <ro...@electricjellyfish.net>.
Rian Hunter wrote:
> Ah I didn't even realize the key allocation, I'll fix that. Thanks!
>
> The reason I don't use an apr_array_t or similar is that I thought that
> the number of elements in that type has to be fixed and can't be
> automatically extended and allocated on the fly, If I'm wrong I can
> change these structures to use apr_array_t (or you can send in a patch
> if you like).
APR arrays are variable length, you use apr_array_push and apr_array_pop
to add and remove entries. I'll throw together the patch sometime today.
-garrett
Re: smtpd_request_rec questions
Posted by Rian Hunter <ri...@MIT.EDU>.
On Aug 14, 2005, at 4:21 PM, Garrett Rooney wrote:
> I was just looking at the smtpd_request_rec in mod_smtpd, and I had
> a few questions.
>
> It seems that extensions and rcpt info is being stored in an
> apr_hash_t, but it's only being keyed by integer. If you're only
> going to use ints as keys, it seems like an apr_array_header_t
> would be more appropriate. Also, while the extensions has is
> specifically allocating its keys, the rcpt_to hash is reusing the
> r_index variable each time, so if more than one entry is added
> things aren't going to work, since that location in memory is
> having its value changed after its been used as a key.
>
> Anyway, I'd be happy to produce patches to either switch to an
> array or fix the key issue in the rcpt_to section, depending on
> which way we want to go. Personally, I'd prefer the array version
> though.
>
> -garrett
>
Ah I didn't even realize the key allocation, I'll fix that. Thanks!
The reason I don't use an apr_array_t or similar is that I thought
that the number of elements in that type has to be fixed and can't be
automatically extended and allocated on the fly, If I'm wrong I can
change these structures to use apr_array_t (or you can send in a
patch if you like).
-rian