import std.stdio;
import std.range;
import std.array;
import std.string;
import std.conv;
import std.typecons;
import std.algorithm;
import std.container;
import std.typecons;
import std.random;
import std.csv;
import std.regex;
import std.math;
import core.time;
import std.ascii;
import std.digest.sha;
import std.outbuffer;
import std.numeric;

void main()
{
	int n, m;
	readln.chomp.split.tie(n, m);
	char[][] board = new char[][](n);
	foreach (i; 0..n) {
		board[i] = readln.chomp.dup;
	}
	bool yes = true;
	enum OFS = [
		[0, 1],
		[1, 0],
		[-1, 0],
		[0, -1],
		[1, 1],
		[1, -1],
		[-1, 1],
		[-1, -1]
	];
	foreach (y; 0..n) {
		foreach (x; 0..m) {
			if (board[y][x] == '*') {
				continue;
			}
			int v;
			if (board[y][x] == '.') {
				v = 0;
			} else {
				v = board[y][x] - '0';
			}
			int cnt = 0;
			foreach (d; OFS) {
				int nx = x + d[0];
				int ny = y + d[1];
				if (nx < 0 || m <= nx
						|| ny < 0 || n <= ny) {
					continue;
				}
				if (board[ny][nx] == '*') {
					++cnt;
				}
			}
			yes &= v == cnt;
		}
	}
	writeln = yes ? "YES" : "NO";
}

void tie(R, Args...)(R arr, ref Args args)
		if (isRandomAccessRange!R || isArray!R)
in
{
	assert (arr.length == args.length);
}
body
{
	foreach (i, ref v; args) {
		alias T = typeof(v);
		v = arr[i].to!T;
	}
}

void verbose(Args...)(in Args args)
{
	stderr.write("[");
	foreach (i, ref v; args) {
		if (i) stderr.write(", ");
		stderr.write(v);
	}
	stderr.writeln("]");
}

