The \dorows expansion is performed all in one swoop, generating the table body, and only then TeX will start to expand it looking for & and \cr tokens, if you hide them in macros. Otherwise TeX will see & and stop the column, inserting the u and v part, typesetting it and storing it away. So the dreaded \endtemplate token will find its way in the argument of \stopcol.
If instead you put & and \cr into macros, these won't be expanded until \dorows has finished its work and the table will be safely built.
Notice that \cr is not outer: the problem is exactly the same as with \stopcol, but with \stoprow.
You can see this by changing your input as follows:
\documentclass{article}
\usepackage{catoptions}
\makeatletter
\cptnewcounts{rowcnt,colcnt,maxrow,maxcol}
\newtoks\ahmed
\def\docols{%
\global\advance\colcnt\@ne
\global\ahmed=\expandafter{\the\expandafter\ahmed\the\numexpr\rowcnt*\colcnt\relax}%
\ifnum\colcnt=\maxcol\stopcol\fi
\global\ahmed=\expandafter{\the\ahmed\samp}\docols
}
\def\stopcol#1\docols{\fi}
\def\samp{&}
\def\dorows{%
\global\advance\rowcnt\@ne
\global\colcnt\z@
\docols
\ifnum\rowcnt=\maxrow\stoprow\fi
\global\ahmed=\expandafter{\the\ahmed\scr}\dorows
}
\def\stoprow#1\dorows{\fi\global\ahmed=\expandafter{\the\ahmed\crcr}}
\def\scr{\cr}
\makeatother
\begin{document}
\maxrow4 \maxcol3
$$\vbox{\halign{&\ \hfil#\hfil\strut\cr\dorows\showthe\ahmed\the\ahmed}}$$
\end{document}
The \show command will output
> 1&2&3\cr 2&4&6\cr 3&6&9\cr 4&8&12\crcr .
l.27 ... \hfil#\hfil\strut\cr\dorows\showthe\ahmed
\the\ahmed}}$$
With this approach you can use & and \cr, because they would be protected by the braces of the token register assignment.