Summary:ASTERISK-08159: powerof(0) can happen with external channel drivers in translate.c
Reporter:HPS (hselasky)Labels:
Date Opened:2006-11-21 03:46:59.000-0600Date Closed:2006-11-30 14:28:38.000-0600
Versions:Frequency of

In "translate.c", powerof(d) can be called with d=0, which yields the following error:

ast_log(LOG_WARNING, "Powerof %d: No power??\n", d);

This happens with external channel drivers that have not been updated:


Use "ast_set_read_format()" and "ast_set_write_format()" to initialize the
format used, hence "chan->lastreadformat" was uninitialized.

    fmt = ast_best_codec(fmt);

+    ast_set_read_format(pbx_chan, fmt);
+    ast_set_write_format(pbx_chan, fmt);


In any bridge routines, don't forward AST_FRAME_NULL.

But still I think asterisk has a bug, in that it cannot handle  
"AST_FRAME_NULL", hence "f->subclass == 0", and it is forwarded by  
"ast_write()" to "ast_translate_write()", which causes a powerof(0) error
with Asterisk 1.2.12+.

In "ast_translate_write()" and possibly the other functions calling powerof() in "translate.c", invalid memory will be accessed if "powerof(0) == -1". Extra checks need to be added to handle that.

Comments:By: Joshua C. Colp (jcolp) 2006-11-21 11:28:30.000-0600

I don't understand what you mean by handling AST_FRAME_NULL. It's purposely ignored in ast_write and doesn't get sent through the translation path. As for having an AST_FRAME_VOICE With a subclass of 0, that should never happen if the code for where the frame came from is written properly. Can you clarify some more?

By: HPS (hselasky) 2006-11-30 10:40:20.000-0600

NOTE: I already replied by e-mail, but it seems like the e-mail got list. At least my notes are not here. So:

Yes, I installed asterisk-1.2.13, and there you will see that:

int ast_write(struct ast_channel *chan, struct ast_frame *fr)
       int res = -1;
       struct ast_frame *f = NULL;
       /* Stop if we're a zombie or need a soft hangup */
       if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))  {
               return -1;
       /* Handle any pending masquerades */
       if (chan->masq) {
               if (ast_do_masquerade(chan)) {
                       ast_log(LOG_WARNING, "Failed to perform
                       return -1;
       if (chan->masqr) {
               return 0;
       if (chan->generatordata) {
               if (ast_test_flag(chan, AST_FLAG_WRITE_INT))
               else {
                       return 0;
       /* High bit prints debugging */
       if (chan->fout & 0x80000000)
               ast_frame_dump(chan->name, fr, ">>");
       switch(fr->frametype) {
       case AST_FRAME_CONTROL:
               /* XXX Interpret control frames XXX */
               ast_log(LOG_WARNING, "Don't know how to handle control frames
       case AST_FRAME_DTMF:
               ast_clear_flag(chan, AST_FLAG_BLOCKING);
               res = do_senddigit(chan,fr->subclass);
       case AST_FRAME_TEXT:
               if (chan->tech->send_text)
                       res = chan->tech->send_text(chan, (char *) fr->data);
                       res = 0;
       case AST_FRAME_HTML:
               if (chan->tech->send_html)
                       res = chan->tech->send_html(chan, fr->subclass, (char
*) fr->data, fr->datalen);
                       res = 0;
       case AST_FRAME_VIDEO:
               /* XXX Handle translation of video codecs one day XXX */
               if (chan->tech->write_video)
                       res = chan->tech->write_video(chan, fr);
                       res = 0;
               if (chan->tech->write) {
                       f = ast_translate_write(chan, fr, 0);


From the code snippet above you see that AST_FRAME_NULL will fall into the
"default" handler, and be forwarded to ast_translate_write(), which then
triggers the bug. So maybe there is a missing "case AST_FRAME_NULL" ?

Does this clarify more ?

By: Joshua C. Colp (jcolp) 2006-11-30 14:28:37.000-0600

Fixed in 1.2 as of revision 48161. Thanks!