package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	for {
		scanner := bufio.NewScanner(os.Stdin)

		// 设置大缓冲区,防止大输入时出错
		buf := make([]byte, 1024*1024) // 1MB
		scanner.Buffer(buf, 1024*1024)
		scanner.Split(bufio.ScanWords) // 按单词扫描(空格、换行等分隔)

		// 读取第一行:n
		scanner.Scan()
		row, _ := strconv.Atoi(scanner.Text())
		if row == 0 {
			break
		}

		scanner.Scan()
		col, _ := strconv.Atoi(scanner.Text())
		if col == 0 {
			break
		}
		arr := make([][]int, row)
		for i := 0; i < row; i++ {
			arr[i] = make([]int, col)
			for j := 0; j < col; j++ {
				scanner.Scan()
				arr[i][j], _ = strconv.Atoi(scanner.Text())
			}
		}
		fmt.Println(process(arr))
	}
}

func process(arr [][]int) int {
	if len(arr) == 0 {
		return 0
	}
	dp := make([]int, len(arr[0]))
	maxarea := 0
	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr[i]); j++ {
			if arr[i][j] == 1 {
				dp[j] += 1
			} else {
				dp[j] = 0
			}
		}

		index := make([]int, 0, len(dp))
		n := len(dp)
	    // 左右边界,求最大面积,单调栈思路
		for k := 0; k <= n; k++ {
			h := 0
			if k < n {
				h = dp[k]
			}
			for len(index) > 0 && h < dp[index[len(index)-1]] {
				height := dp[index[len(index)-1]]
				index = index[:len(index)-1]
				width := k
				if len(index) > 0 {
					width = k - index[len(index)-1] - 1
				}
				maxarea = max(maxarea, height*width)
			}
			index = append(index, k)
		}

	}
	return maxarea
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}