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-0600 | Date Closed: | 2006-11-30 14:28:38.000-0600 |
Priority: | Minor | Regression? | No |
Status: | Closed/Complete | Components: | Core/General |
Versions: | Frequency of Occurrence | ||
Related Issues: | |||
Environment: | Attachments: | ||
Description: | Hi, 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: 1) 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); + 2) 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. --HPS | ||
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 */ ast_mutex_lock(&chan->lock); if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { ast_mutex_unlock(&chan->lock); return -1; } /* Handle any pending masquerades */ if (chan->masq) { if (ast_do_masquerade(chan)) { ast_log(LOG_WARNING, "Failed to perform masquerade\n"); ast_mutex_unlock(&chan->lock); return -1; } } if (chan->masqr) { ast_mutex_unlock(&chan->lock); return 0; } if (chan->generatordata) { if (ast_test_flag(chan, AST_FLAG_WRITE_INT)) ast_deactivate_generator(chan); else { ast_mutex_unlock(&chan->lock); return 0; } } /* High bit prints debugging */ if (chan->fout & 0x80000000) ast_frame_dump(chan->name, fr, ">>"); CHECK_BLOCKING(chan); switch(fr->frametype) { case AST_FRAME_CONTROL: /* XXX Interpret control frames XXX */ ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n"); break; case AST_FRAME_DTMF: ast_clear_flag(chan, AST_FLAG_BLOCKING); ast_mutex_unlock(&chan->lock); res = do_senddigit(chan,fr->subclass); ast_mutex_lock(&chan->lock); CHECK_BLOCKING(chan); break; case AST_FRAME_TEXT: if (chan->tech->send_text) res = chan->tech->send_text(chan, (char *) fr->data); else res = 0; break; case AST_FRAME_HTML: if (chan->tech->send_html) res = chan->tech->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen); else res = 0; break; 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); else res = 0; break; default: 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! |